web-dev-qa-db-ja.com

$ scopeで複数のイベントをリッスンします

一部の関数を$scope.$onでローカルスコープにバインドするディレクティブがあります。

同じ関数を1回の呼び出しで複数のイベントにバインドすることは可能ですか?

理想的には次のようなことができるでしょう:

app.directive('multipleSadness', function() {
    return {
        restrict: 'C',
        link: function(scope, elem, attrs) {
            scope.$on('event:auth-loginRequired event:auth-loginSuccessful', function() {
                console.log('The Ferrari is to a Mini what AngularJS is to ... other JavaScript frameworks');
            });
        }
    };
});

しかし、これは機能しません。カンマ区切りのイベント名文字列を['event:auth-loginRequired', 'event:auth-loginConfirmed']に置き換えた同じ例でも、動作しません。

何が機能するのですか?

app.directive('multipleSadness', function() {
    return {
        restrict: 'C',
        link: function(scope, elem, attrs) {

            scope.$on('event:auth-loginRequired', function() {
                console.log('The Ferrari is to a Mini what AngularJS is to ... other JavaScript frameworks');
            });
            scope.$on('event:auth-loginConfirmed', function() {
                console.log('The Ferrari is to a Mini what AngularJS is to ... other JavaScript frameworks');
            });
        }
    };
});

しかし、これは理想的ではありません。

一度に複数のイベントを同じ関数にバインドすることは可能ですか?

20

はい。このような:

app.directive('multipleSadness', function() {
    return {
        restrict: 'C',
        link: function(scope, elem, attrs) {

            function sameFunction(eventId) {
                console.log('Event: ' + eventId + '. The Ferrari is to a Mini what AngularJS is to ... other JavaScript frameworks.');
            }

            scope.$on('event:auth-loginRequired', function() {sameFunction('auth-loginRequired');});
            scope.$on('event:auth-loginConfirmed', function () {sameFunction('auth-loginConfirmed');});
        }
    };
});

しかし、それができるからといって、そうすべきではないということです。イベントが別のリスナーまで伝播し続け、そこで別の方法で処理される場合は、おそらくこれを行うケースがあります。これが唯一のリスナーになる場合は、同じイベントを送信(またはブロードキャスト)するだけで十分です。

13
testing123

他の答え(Anders Ekdahl)は100%正解です...そのうちの1つを選んでください...しかし...

それを除けば、あなたはいつでも自分でロールすることができます:

_// a hack to extend the $rootScope 
app.run(function($rootScope) {
   $rootScope.$onMany = function(events, fn) {
      for(var i = 0; i < events.length; i++) {
         this.$on(events[i], fn);
      }
   }
});

app.directive('multipleSadness', function() {
    return {
        restrict: 'C',
        link: function(scope, elem, attrs) {
            scope.$onMany(['event:auth-loginRequired', 'event:auth-loginSuccessful'], function() {
                console.log('The Ferrari is to a Mini what AngularJS is to ... other JavaScript frameworks');
            });
        }
    };
});
_

あなたが本当に.split(',')をやりたいと思ったとしたら、それは実装の詳細です。

29
Ben Lesh

AngularJSは複数のイベントバインディングをサポートしていませんが、次のようなことができます。

var handler = function () { ... }
angular.forEach("event:auth-loginRequired event:auth-loginConfirmed".split(" "), function (event) {
    scope.$on(event, handler);
});
14
bmleite

イベントがコールバックにデータを送信する可能性があるため、それは可能ではないと思います。複数のイベントをリッスンした場合、どのイベントからどのデータが送信されたかはわかりません。

私はこのようなことをしたでしょう:

function listener() {
    console.log('event fired');
}
scope.$on('event:auth-loginRequired', listener);
scope.$on('event:auth-loginConfirmed', listener);
7
Anders Ekdahl

また、$ rootScope。$ onMany(@ ben-leshからのソリューション)と同様に、$ onメソッドを拡張することができます。

var $onOrigin = $rootScope.$on;

$rootScope.$on = function(names, listener) {
  var self = this;

  if (!angular.isArray(names)) {
    names = [names];
  }

  names.forEach(function(name) {
    $onOrigin.call(self, name, listener);
  });

};

こちら から取得。

1
Stepan Suvorov