Skip to content

Commit

Permalink
feat($rootScope): adds $onRootScope method
Browse files Browse the repository at this point in the history
This adds an $onRootScope method to the
scope type. This allows developers to use
$rootScope.$emit + $scope.$onRootScope as
a fast eventBus which doesn't use scope
bubbleing.

Fixes angular#4574, Relates to angular#5371
  • Loading branch information
cburgdorf committed Dec 21, 2013
1 parent 937caab commit 489836d
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 0 deletions.
37 changes: 37 additions & 0 deletions src/ng/rootScope.js
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,43 @@ function $RootScopeProvider(){
};
},

/**
* @ngdoc function
* @name ng.$rootScope.Scope#$onRootScope
* @methodOf ng.$rootScope.Scope
* @function
*
* @description
* Listens on events of a given type. See {@link ng.$rootScope.Scope#methods_$emit $emit} for
* discussion of event life cycle. This method is similar to the $on method with the only difference
* that it subscribes to events emitted on the $rootScope. This allows to use $rootScope.$emit for
* application wide events rather than $rootScope.$broadcast. For an in detail explanation of why
* to use $rootScope.$emit rather than $rootScope.$broadcast please read this answer on StackOverflow:
* http://stackoverflow.com/questions/11252780/whats-the-correct-way-to-communicate-between-controllers-in-angularjs/19498009#19498009
*
* The event listener function format is: `function(event, args...)`. The `event` object
* passed into the listener has the following attributes:
*
* - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or
* `$broadcast`-ed.
* - `currentScope` - `{Scope}`: the current scope which is handling the event.
* - `name` - `{string}`: name of the event.
* - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel
* further event propagation (available only for events that were `$emit`-ed).
* - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag
* to true.
* - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
*
* @param {string} name Event name to listen on.
* @param {function(event, args...)} listener Function to call when the event is emitted.
* @returns {function()} Returns a deregistration function for this listener.
*/
$onRootScope: function(name, listener) {
var unsubscribe = this.$root.$on(name, listener);
this.$on('$destroy', unsubscribe);

return unsubscribe;
},

/**
* @ngdoc function
Expand Down
66 changes: 66 additions & 0 deletions test/ng/rootScopeSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1116,6 +1116,72 @@ describe('Scope', function() {
}));
});

describe('$onRootScope', function() {

it('should add listener for both $emit and $broadcast events that are triggered on $rootScope', inject(function($rootScope) {
var log = '',
child = $rootScope.$new();

function eventFn() {
log += 'X';
}

child.$onRootScope('abc', eventFn);
expect(log).toEqual('');

$rootScope.$emit('abc');
expect(log).toEqual('X');

$rootScope.$broadcast('abc');
expect(log).toEqual('XX');
}));


it('should return a function that deregisters the listener', inject(function($rootScope) {
var log = '',
child = $rootScope.$new(),
listenerRemove;

function eventFn() {
log += 'X';
}

listenerRemove = child.$onRootScope('abc', eventFn);
expect(log).toEqual('');
expect(listenerRemove).toBeDefined();

$rootScope.$emit('abc');
$rootScope.$broadcast('abc');
expect(log).toEqual('XX');

log = '';
listenerRemove();
$rootScope.$emit('abc');
$rootScope.$broadcast('abc');
expect(log).toEqual('');
}));

it('should remove listener when local scope gets destroyed', inject(function($rootScope) {
var log = '',
child = $rootScope.$new();

function eventFn() {
log += 'X';
}

child.$onRootScope('abc', eventFn);
expect(log).toEqual('');

$rootScope.$emit('abc');
expect(log).toEqual('X');

child.$destroy();

$rootScope.$emit('abc');
expect(log).toEqual('X');
}));

});

describe('$emit', function() {
var log, child, grandChild, greatGrandChild;
Expand Down

0 comments on commit 489836d

Please sign in to comment.