Event based communication between controllers.
Every angular application has a single root Scope ($rootScope). All the scopes are its descendants.
Scopes can generate an events by emitting ($emit) or broadcasting ($broadcast). Apart from generating events, scope can listen to events as well. Its is achieved by using the $scope.$on
$emit, $broadcast and $on follow the standard "publish / subscribe" design pattern.
Understanding the $scope methods for event based communication between angular controllers
Every angular application has a single root Scope ($rootScope). All the scopes are its descendants.
Scopes can generate an events by emitting ($emit) or broadcasting ($broadcast). Apart from generating events, scope can listen to events as well. Its is achieved by using the $scope.$on
$emit, $broadcast and $on follow the standard "publish / subscribe" design pattern.
Understanding the $scope methods for event based communication between angular controllers
- $scope.$emit: This method dispatches the event in the upwards direction (from child to parent)
- $scope.$broadcast: Method dispatches the event in the downwards direction (from parent to child) to all the child controllers.
- $scope.$on: Method registers to listen to some event. All the controllers which are listening to that event gets notification of the broadcast or emit based on the where those fit in the child parent hierarchy.
If we consider a case where "grand_child" controller calls the $emits method on its scope. The same "grand_child" controller has also listening to the same event which is emitted by itself. In this situation when "grand_child" calls $emit, the same controller gets its own notification.
Essentially all the controllers in the hierarchy gets notification for $emit (in upwards direction).
Note : In case of sibling scopes (the scopes which are not in the direct parent child hierarchy) then $emit and $broadcast will not communicate to the sibling scopes.
$rootScope.$broadcast: $rootScope is the parent of all the scopes. $rootScope.$broadcast will notify the event to all the controllers listening to $rootScope.$on as well as $scope.on
$rootScope.$emit : We may think that calling $emit method is meaning-less as rootScope do not have any parent. But actually $rootScope.$emit fires an event to all the controllers listening $rootScope.$on event. The controllers which are listening on $scope.$on have no effect of this emit.
Stopping the event being propagating
The $emit event can be cancelled by any one of the $scope who is listening to the event.
The $on provides the "stopPropagation" method. By calling this method the event can be stopped from propagating further.
This method is available only for the events which are emitted($emit). The same is not available for $broadcast.
The events which are broadcast can't be stopped. Although we can registered the scope from listening the event.
$on function returns a function.
.controller('T1Parent',['$scope',function($scope){ $scope.T1EventVar = ''; $scope.stopPropagation=false; $scope.stopBroadcast = false; var fn = $scope.$on('Tree1Event',function(e,arg){ $scope.T1EventVar = arg; if($scope.stopPropagation) { e.stopPropagation(); } if($scope.stopBroadcast){ fn(); // This will cancel the listening of the event 'Tree1Event' } }); $scope.broadCastEvent=function(){ $scope.$broadcast('Tree1Event','T1 Parent Brodacated'); }; $scope.emitEvent=function(){ $scope.$emit('Tree1Event','T1 Parent Emitted'); }; }])
The complete example can be see on the following plunk. This example demonstrates the emit, broadcast, rootScope.$emit, rootScope.$broadcast, stopping the propagation and cancelling the listening of the event from a particular controller's scope.
Demo http://plnkr.co/edit/0Pdrrtj3GEnMp2UpILp4?p=preview
source code emit-vs-broadcast.js
Source HTML:
Demo http://plnkr.co/edit/0Pdrrtj3GEnMp2UpILp4?p=preview
source code emit-vs-broadcast.js
angular.module('dlgDemo',[]) .controller('GrandParent1',['$scope','$rootScope',function($scope,$rootScope){ $scope.GrandParent1Var = ''; //Listening the Tree 1 Child Event $scope.$on('T1childEmitEvent',function(e,arg){ console.log("Hello"); $scope.T1EventVar = arg; }); // Listening to Tree 2 Grand Parent Event $scope.$on('Tree1Event',function(e,arg){ $scope.T1EventVar = arg; }); $scope.broadCastEvent=function(){ console.log("broadCastEvent"); $scope.$broadcast('Tree1Event','T1 Grand Parent Brodacated'); }; $scope.emitEvent=function(){ $scope.$emit('Tree1Event','T1 Grand Parent Emitted'); }; $scope.rootBroadcast = function() { $rootScope.$broadcast('Tree1Event','$rootScope.$broadcast'); }; $scope.rootEmit = function() { $rootScope.$emit('Tree1Event','$rootScope.$emit'); }; }]) .controller('T1Parent',['$scope',function($scope){ $scope.T1EventVar = ''; $scope.stopPropagation=false; var fn = $scope.$on('Tree1Event',function(e,arg){ console.log(e); $scope.T1EventVar = arg; if($scope.stopPropagation) { e.stopPropagation(); } if($scope.stopBroadcast){ fn(); } }); $scope.broadCastEvent=function(){ $scope.$broadcast('Tree1Event','T1 Parent Brodacated'); }; $scope.emitEvent=function(){ $scope.$emit('Tree1Event','T1 Parent Emitted'); }; }]) .controller('T1Child',['$scope','$rootScope',function($scope,$rootScope){ $scope.T1EventVar = ''; $scope.T1EventVarFromRoot = ''; $scope.$on('Tree1Event',function(e,arg){ console.log(e); $scope.T1EventVar = arg; }); $scope.emitEvent = function() { $scope.$emit('Tree1Event','T1 Child Emitted'); }; $scope.broadCastEvent=function(){ //$scope.$broadcast('Tree1Event','T1 Child Brodacated'); $rootScope.$broadcast('Tree1Event','$rootScope.$broadcast'); }; $rootScope.$on('Tree1Event', function(e,arg){ $scope.T1EventVar = arg; }); }]) .controller('GrandParent2',['$scope',function($scope){ $scope.T1EventVar = ''; //Listening the Tree 1 Child Event $scope.$on('Tree1Event',function(e,arg){ $scope.T1EventVar = arg; }); $scope.broadCastEvent=function(){ $scope.$broadcast('Tree1Event','T2 Grand Parent Brodacated'); }; $scope.emitEvent=function(){ $scope.$emit('Tree1Event','T2 Grand Parent Emitted'); }; }]) .controller('T2Parent',['$scope',function($scope){ $scope.T1EventVar = ''; $scope.$on('Tree1Event',function(e,arg){ $scope.T1EventVar = arg; }); $scope.emitEvent = function() { $scope.$emit('Tree1Event','T2 Parent Emitted'); }; $scope.broadCastEvent=function(){ $scope.$broadcast('Tree1Event','T2 Parent Brodacated'); }; }]) .controller('T2Child',['$scope',function($scope){ $scope.T1EventVar = ''; $scope.$on('Tree1Event',function(e,arg){ $scope.T1EventVar = arg; }); $scope.emitEvent = function() { $scope.$emit('Tree1Event','T2 Child Emitted'); }; $scope.broadCastEvent=function(){ $scope.$broadcast('Tree1Event','T2 Child Brodacated'); }; }]);
Source HTML:
Tree 1 : Grand parant
Event Event Listener1 {{T1EventVar}}
Tree 1 : Parent
Stop Propagation Emit eventDeregister the scope from listening event
Event Event Listener1 {{T1EventVar}} Tree 1 : Grand Child
Event Event Listener1 {{T1EventVar}}
Tree 2 : Grand parant
Event Event Listener1 {{T1EventVar}}
Tree 2 : Parent
Event Event Listener1 {{T1EventVar}} Tree 2 : Grand Child
Event Event Listener1 {{T1EventVar}}