web-dev-qa-db-fra.com

Écoutez plusieurs événements sur une portée $

J'ai une directive qui lie certaines fonctions à la portée locale avec $scope.$on.

Est-il possible de lier la même fonction à plusieurs événements en un seul appel?

Idéalement, je serais capable de faire quelque chose comme ça:

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');
            });
        }
    };
});

Mais ça ne marche pas. Le même exemple avec la chaîne de nom d'événement séparée par des virgules remplacée par ['event:auth-loginRequired', 'event:auth-loginConfirmed'] ne fonctionne pas non plus.

Qu'est-ce qui fonctionne, c'est ceci:

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');
            });
        }
    };
});

Mais ce n'est pas idéal.

Est-il possible de lier plusieurs événements à la même fonction en une seule fois?

20
Michael Robinson

Oui. Comme ça:

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');});
        }
    };
});

Mais ce n'est pas parce que vous le pouvez que vous devriez :). Si les événements continuent de se propager à un autre auditeur et qu'ils y sont traités différemment, il y a peut-être lieu de le faire. Si cela doit être le seul auditeur, vous devez simplement émettre (ou diffuser) le même événement.

13
testing123

Les autres réponses (Anders Ekdahl) sont correctes à 100% ... choisissez-en une ... MAIS ...

Sauf cela, vous pouvez toujours lancer le vôtre:

// 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');
            });
        }
    };
});

Je suppose que si vous vouliez vraiment faire la .split(',') vous le pouviez, mais c'est un détail d'implémentation.

29
Ben Lesh

AngularJS ne prend pas en charge la liaison d'événements multiples, mais vous pouvez faire quelque chose comme ceci:

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

Je ne pense pas que ce soit possible, car l'événement pourrait envoyer des données au rappel, et si vous écoutez plusieurs événements, vous ne sauriez pas quelles données provenaient de quel événement.

J'aurais fait quelque chose comme ça:

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

Comme avec $ rootScope. $ OnMany (solution de @ ben-lesh) il est possible d'étendre la méthode $ 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);
  });

};

a pris de ici .

1
Stepan Suvorov