4

I have potentially multiple $rootScope.$broadcast events affecting one view element. I would like to have a hierarchical function to decide which event takes precedence for effecting the view.

My question is, how can I listen to all events $broadcasted on the $rootScope? Is there some kind of event interceptor?

roscioli
  • 1,200
  • 3
  • 15
  • 33

3 Answers3

9

I was searching for solutions for the same problem. Came across caitp's solution at https://github.com/angular/angular.js/issues/6043 which I believe is what you were looking for as well.

This has the advantage that you can leave it in development and simply not include it in production code, without changing any logic in you application.

I'll copy the code from the link for posterity, with minor adjustments (to work with current versions of angular):

app.config(function($provide) {
    $provide.decorator("$rootScope", function($delegate) {
    var Scope = $delegate.constructor;
    var origBroadcast = Scope.prototype.$broadcast;
    var origEmit = Scope.prototype.$emit;

    Scope.prototype.$broadcast = function() {
      console.log("$broadcast was called on $scope " + this.$id + " with arguments:",
                     arguments);
      return origBroadcast.apply(this, arguments);
    };
    Scope.prototype.$emit = function() {
      console.log("$emit was called on $scope " + this.$id + " with arguments:",
                     arguments);
      return origEmit.apply(this, arguments);
    };
    return $delegate;
    });
});

More info about $provide.decorate:

[1] http://blog.xebia.com/extending-angularjs-services-with-the-decorate-method/

[2] https://docs.angularjs.org/api/auto/service/$provide

Adrian B.
  • 1,592
  • 1
  • 20
  • 38
  • nice way, I was looking for something like .provider but this do the trick, should be the accepted answer I think. – sebius Apr 03 '18 at 08:28
8

You cannot really do that, and that would be an anti-pattern.

Instead, you should create a service that handle events emission and processing so you can do all this logic from there:

module.service('events', function($rootScope) {
  var onAllCallbacks = [];

  this.broadcast = function(name, data) {
    $rootScope.$broadcast(name, data);
    onAllCallbacks.forEach(function(cb) { cb(name, data); });
  }

  this.on = function(name, callback) {
    $rootScope.$on(name, callback);
  }

  this.onAll = function(callback) {
    onAllCallbacks.push(callback);
  }
})

Then in your code

events.onAll(function(name, data) {
  console.log('Broadcasted event:', name, data);
});

events.broadcast('foo', data1);
events.broadcast('bar', data2);

That way you would only use events.broadcast to broadcast events that you want to be aware of from the onAll listener.

floribon
  • 19,175
  • 5
  • 54
  • 66
-3

$rootScope.$broadcast automatically will 'broadcast' the results of that variable/ object. When you need on the other end, is the listener - $rootScope.$on. It looks like this:

//broadcast
$rootScope.$broadcast('variableName');

//listener
$rootScope.$on('variableName', function(event, args){
    //do whatever you want in here when 'variableName' is broadcasted
});
jadams
  • 195
  • 1
  • 8
  • Hey thanks for trying to help, but what I need to know is how to intercept _all_ broadcasted events. – roscioli Apr 01 '15 at 20:56
  • 1
    you can set a watch on a collection of variables `$rootScope.$watchGroup(['var1','var2', 'var3'], function(event,args){ do stuff });` – jadams Apr 28 '15 at 20:19
  • watchGroup doesn't intercept broadcasted events but expressions that are in the scope, so that's unrelated – floribon Oct 11 '16 at 09:21