web-dev-qa-db-ja.com

別のattrで定義されたディレクティブattr内のコールバック関数

つまり、mySaveという名前のこのディレクティブがあります。これはほとんどこれです

app.directive('mySave', function($http) {
   return function(scope, element, attrs) {
      element.bind("click", function() {
          $http.post('/save', scope.data).success(returnedData) {
              // callback defined on my utils service here

              // user defined callback here, from my-save-callback perhaps?
          }
      });
   }
});

要素自体は次のようになります

<button my-save my-save-callback="callbackFunctionInController()">save</button>

callbackFunctionInControllerは今のところ

$scope.callbackFunctionInController = function() {
    alert("callback");
}

my-saveディレクティブ内でconsole.log()attrs.mySaveCallbackを実行すると、文字列callbackFunctionInController()が返されるだけで、 somewhere これを$ parseする必要があり、それで問題ないので、$parse(attrs.mySaveCallback)を試して、いくつかの機能を返しましたが、探していたものはほとんどありませんでした。

function (a,b){return m(a,b)} 

何が間違っていますか?このアプローチは最初から欠陥がありますか?

38
fxck

ProLoserで提案されているように、分離されたスコープを使用するのが最良の方法のように思えます

app.directive('mySave', function($http) {
   return {
      scope: {
        callback: '&mySaveCallback'
      }
      link: function(scope, element, attrs) {
        element.on("click", function() {
            $http.post('/save', scope.$parent.data).success(returnedData) {
                // callback defined on my utils service here

                scope.callback(); // fires alert
            }
        });
      }
   }
});

パラメーターをコントローラーに戻すには、これを行います

[11:28] <revolunet> you have to send named parameters 
[11:28] <revolunet> eg my-attr="callback(a, b)" 
[11:29] <revolunet> in the directive: scope.callback({a:xxx, b:yyy})
61
fxck

あなたがしていることを実行する方法はたくさんあります。最初に知っておくべきことは、テンプレートエンジンによってDOM要素がレンダリングされるとすぐに$http.post()が呼び出されるということです。リピート内に配置すると、リピーター内の新しいアイテムごとに呼び出しが行われるため、これは間違いなくあなたが望むものではないでしょう。そして、それがisである場合、DOMの存在だけではバックエンドへのクエリを指示するべきではないため、実際には正しく設計できません。

とにかく、あなたの質問に直接答えます。 $ parseで安っぽいドキュメントを読んだ場合、評価式が返されます。評価するスコープを渡してこの関数を実行すると、渡したスコープの式の現在の状態が返されます。これは、関数が実行されることを意味します。

_var expression = $parse(attrs.mySave);
results = expression($scope); // call on demand when needed
expression.assign($scope, 'newValu'); // the major reason to leverage $parse, setting vals
_

はい、最初は少し混乱しますが、非同期アプリでは$ scopeが絶えず変化することを理解する必要があります。 _$parse_は、単に読み取るだけでなく、値を割り当てることができるモデルへの参照に役立ちます。

もちろん、分離スコープの作成や式の$eval()方法については、読んでおくとよいでしょう。

_$scope.$eval(attrs.mySave);
_
12
ProLoser

。$ eval を使用して、指定されたスコープでステートメントを実行できます。

app.directive('mySave', function($http) {
   return function(scope, element, attrs) {
      $http.post('/save', scope.data).success(returnedData) {
          // callback defined on my utils service here

          // user defined callback here, from my-save-callback perhaps?
          scope.$eval(attrs.mySaveCallback)
      }
   }
});

TD: デモ

ディレクティブとコントローラー間でデータを共有したい場合は、双方向バインディングを使用できます

app.controller('AppController', function ($scope) {
   $scope.callbackFunctionInController = function() {
      console.log('do something')
   };

   $scope.$watch('somedata', function(data) {
      console.log('controller', data);
   }, true);
});

app.directive('mySave', function($http, $parse) {
   return {
     scope: {
       data: '=mySaveData',
       callback: '&mySaveCallback' //the callback
     },
     link: function(scope, element, attrs) {
       $http.get('data.json').success(function(data) {
         console.log('data', data);
         scope.data = data;
         scope.callback(); //calling callback, this may not be required
       });
     }
   };
});

デモ: フィドル

9
Arun P Johny
_scope: {
    callback: '&mySaveCallback'
}
_

スコープを明示的に設定することは良い解決策かもしれませんが、元のスコープの他の部分に到達したい場合は、上書きしただけなのでできません。何らかの理由で、スコープの他の部分にも到達する必要があったため、ng-clickと同じ実装を使用しました。

HTMLでのディレクティブの使用:

<div my-data-table my-source="dataSource" refresh="refresh(data)">

ディレクティブ内(スコープを明示的に設定せずに):

_var refreshHandler = $parse(attrs.refresh);
    scope.$apply(function () {
    refreshHandler( {data : conditions}, scope, { $event: event });
});
_

これにより、コントローラーの関数を呼び出してパラメーターを渡すことができます。

コントローラー内:

_$scope.refresh= function(data){
    console.log(data);
}
_

そして、条件を正しく出力します。

4
Ferenc Kun
app.directive('mySave', function($http, $parse) {
   return {
     scope: {
       data: '=mySaveData',
       callback: '&' //the callback
     },
     link: function(scope, element, attrs) {
       $http.get('data.json').success(function(data) {
         console.log('data', data);
         if (scope.callback()) scope.callback().apply(data);
       });
     }
   };
});
0
ido niger

独自のディレクティブを作成する代わりに、ng-clickを使用する必要があります。

0
ProLoser

これは私のために働いた

ビュースクリプト内

<tag mycallbackattrib="scopemethod">

ディレクティブ内

$scope[attrs.mycallbackattrib](params....);

正しく呼び出され、paramsが渡されますが、動作するのに最適な「角度のある方法」ではない可能性があります。

0
Sergio Rinaudo