How to intercept all $rootScope.$broadcast events in angular.js
Asked Answered
T

3

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?

Tyndall answered 1/4, 2015 at 19:49 Comment(0)
C
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.

Cancellation answered 1/4, 2015 at 21:9 Comment(0)
H
10

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

Handyman answered 20/1, 2016 at 15:0 Comment(1)
nice way, I was looking for something like .provider but this do the trick, should be the accepted answer I think.Bole
C
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.

Cancellation answered 1/4, 2015 at 21:9 Comment(0)
V
-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
});
Vauban answered 1/4, 2015 at 20:33 Comment(3)
Hey thanks for trying to help, but what I need to know is how to intercept all broadcasted events.Tyndall
you can set a watch on a collection of variables $rootScope.$watchGroup(['var1','var2', 'var3'], function(event,args){ do stuff });Vauban
watchGroup doesn't intercept broadcasted events but expressions that are in the scope, so that's unrelatedCancellation

© 2022 - 2024 — McMap. All rights reserved.