Skip to content

Commit 489836d

Browse files
committed
feat($rootScope): adds $onRootScope method
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
1 parent 937caab commit 489836d

File tree

2 files changed

+103
-0
lines changed

2 files changed

+103
-0
lines changed

src/ng/rootScope.js

+37
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,43 @@ function $RootScopeProvider(){
890890
};
891891
},
892892

893+
/**
894+
* @ngdoc function
895+
* @name ng.$rootScope.Scope#$onRootScope
896+
* @methodOf ng.$rootScope.Scope
897+
* @function
898+
*
899+
* @description
900+
* Listens on events of a given type. See {@link ng.$rootScope.Scope#methods_$emit $emit} for
901+
* discussion of event life cycle. This method is similar to the $on method with the only difference
902+
* that it subscribes to events emitted on the $rootScope. This allows to use $rootScope.$emit for
903+
* application wide events rather than $rootScope.$broadcast. For an in detail explanation of why
904+
* to use $rootScope.$emit rather than $rootScope.$broadcast please read this answer on StackOverflow:
905+
* http://stackoverflow.com/questions/11252780/whats-the-correct-way-to-communicate-between-controllers-in-angularjs/19498009#19498009
906+
*
907+
* The event listener function format is: `function(event, args...)`. The `event` object
908+
* passed into the listener has the following attributes:
909+
*
910+
* - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or
911+
* `$broadcast`-ed.
912+
* - `currentScope` - `{Scope}`: the current scope which is handling the event.
913+
* - `name` - `{string}`: name of the event.
914+
* - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel
915+
* further event propagation (available only for events that were `$emit`-ed).
916+
* - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag
917+
* to true.
918+
* - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
919+
*
920+
* @param {string} name Event name to listen on.
921+
* @param {function(event, args...)} listener Function to call when the event is emitted.
922+
* @returns {function()} Returns a deregistration function for this listener.
923+
*/
924+
$onRootScope: function(name, listener) {
925+
var unsubscribe = this.$root.$on(name, listener);
926+
this.$on('$destroy', unsubscribe);
927+
928+
return unsubscribe;
929+
},
893930

894931
/**
895932
* @ngdoc function

test/ng/rootScopeSpec.js

+66
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,72 @@ describe('Scope', function() {
11161116
}));
11171117
});
11181118

1119+
describe('$onRootScope', function() {
1120+
1121+
it('should add listener for both $emit and $broadcast events that are triggered on $rootScope', inject(function($rootScope) {
1122+
var log = '',
1123+
child = $rootScope.$new();
1124+
1125+
function eventFn() {
1126+
log += 'X';
1127+
}
1128+
1129+
child.$onRootScope('abc', eventFn);
1130+
expect(log).toEqual('');
1131+
1132+
$rootScope.$emit('abc');
1133+
expect(log).toEqual('X');
1134+
1135+
$rootScope.$broadcast('abc');
1136+
expect(log).toEqual('XX');
1137+
}));
1138+
1139+
1140+
it('should return a function that deregisters the listener', inject(function($rootScope) {
1141+
var log = '',
1142+
child = $rootScope.$new(),
1143+
listenerRemove;
1144+
1145+
function eventFn() {
1146+
log += 'X';
1147+
}
1148+
1149+
listenerRemove = child.$onRootScope('abc', eventFn);
1150+
expect(log).toEqual('');
1151+
expect(listenerRemove).toBeDefined();
1152+
1153+
$rootScope.$emit('abc');
1154+
$rootScope.$broadcast('abc');
1155+
expect(log).toEqual('XX');
1156+
1157+
log = '';
1158+
listenerRemove();
1159+
$rootScope.$emit('abc');
1160+
$rootScope.$broadcast('abc');
1161+
expect(log).toEqual('');
1162+
}));
1163+
1164+
it('should remove listener when local scope gets destroyed', inject(function($rootScope) {
1165+
var log = '',
1166+
child = $rootScope.$new();
1167+
1168+
function eventFn() {
1169+
log += 'X';
1170+
}
1171+
1172+
child.$onRootScope('abc', eventFn);
1173+
expect(log).toEqual('');
1174+
1175+
$rootScope.$emit('abc');
1176+
expect(log).toEqual('X');
1177+
1178+
child.$destroy();
1179+
1180+
$rootScope.$emit('abc');
1181+
expect(log).toEqual('X');
1182+
}));
1183+
1184+
});
11191185

11201186
describe('$emit', function() {
11211187
var log, child, grandChild, greatGrandChild;

0 commit comments

Comments
 (0)