Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Listen for multiple events on a $scope

I have a directive that binds some functions to the local scope with $scope.$on.

Is it possible to bind the same function to multiple events in one call?

Ideally I'd be able to do something like this:

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

But this doesn't work. The same example with the comma-separated event name string replaced with ['event:auth-loginRequired', 'event:auth-loginConfirmed'] doesn't wrk either.

What does work is this:

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

But this is not ideal.

Is it possible to bind multiple events to the same function in one go?

like image 690
Michael Robinson Avatar asked Feb 12 '13 13:02

Michael Robinson


4 Answers

The other answers (Anders Ekdahl) are 100% correct... pick one of those... BUT...

Barring that, you could always roll your own:

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

I suppose if you really wanted to do the .split(',') you could, but that's an implementation detail.

like image 77
Ben Lesh Avatar answered Nov 18 '22 16:11

Ben Lesh


AngularJS does not support multiple event binding but you can do something like this:

var handler = function () { ... }
angular.forEach("event:auth-loginRequired event:auth-loginConfirmed".split(" "), function (event) {
    scope.$on(event, handler);
});
like image 40
bmleite Avatar answered Nov 18 '22 17:11

bmleite


Yes. Like this:

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

But just because you can, doesn't mean you should :). If the events are continue to propagate up to another listener and they are handled differently there, then maybe there is a case to do this. If this is going to be the only listener than you should just emit (or broadcast) the same event.

like image 13
testing123 Avatar answered Nov 18 '22 16:11

testing123


I don't think that's possible, since the event might send data to the callback, and if you listen to multiple events you wouldn't know which data came from which event.

I would have done something like this:

function listener() {
    console.log('event fired');
}
scope.$on('event:auth-loginRequired', listener);
scope.$on('event:auth-loginConfirmed', listener);
like image 8
Anders Ekdahl Avatar answered Nov 18 '22 18:11

Anders Ekdahl