If you are new to AngularJS I would prefer to go through my introduction blog on AngularJS before read this article. Also before proceed with this article you should have a better understanding about $scope and $rootScope. If you are not aware of that read angular documentation.
Angular $emit, $broadcast and $on service will do exactly same thing as Observer design pattern do. If i put it in other way publish an event and subscribe/unsubscribe to it somewhere else. The Angular event system is brilliant, it makes things flawless and easy to do. Before go to deep I will give a quick understanding about the difference between three.
- $scope.$emit will fire an event up the $scope.
- $scope.$broadcast will fire an eventdown the $scope.
- $scope.$on is how we listen for these events.
See the signature of each below
// firing an event
upwards
$scope.$emit('eventname',
'data to send');
// firing an event
downwards
$scope.$broadcast('eventname',
{
property: 'this is my
object'
});
// listen for the
event in the relevant $scope
$scope.$on('eventname',
function (event, data) {
console.log(data); //logging
data
});
$scope.$broadcast
$scope.$broadcast will fire event downwards of the $scope. Assume we have two controllers, a parent controller and a child controller. If I $broadcast an even from parent controller it always it always will reach $on service in the child controller. $on is the service which is listening for the events propagating from $broadcast/$emit services. See the example below,
eventModule.controller('ParentController', function ($scope) {
$scope.ParentData = "Only those who dare to fail greatly can ever achieve
greatly";
$scope.SendMessageToChild = function () {
$scope.$broadcast("sampleEvent",
$scope.ParentData);
}
});
eventModule.controller("ChildController", function ($scope) {
$scope.$on("sampleEvent", function (event, data) {
$scope.ChildData = "Message from parent controller: " + data;
});
});
and view (html ) below,
<html ng-app="eventModule">
<head>
<title></title>
</head>
<body>
<div ng-controller="ParentController">
Parent Controller : {{ParentData}}
<br />
<input type="button" value="BroadCastEventToChild" ng-click="SendMessageToChild()"/>
<div ng-controller="ChildController">
Child Controller : {{ChildData}}
</div>
</div>
<script src="Scripts/AngularJS/angular.min.js"></script>
<script src="Scripts/Module/EventModule.js"></script>
<script src="Scripts/Controllers/ParentController.js"></script>
<script src="Scripts/Controllers/ChildController.js"></script>
</body>
</html>
So as I explained before I have created two controllers, ParentController and ChildController. In ParentController I have a function SendMessageToChild which will call click event of BroadCastEvent' button. In SendMessageToChild function I am calling $scope.$broadcast function in which first parameter is event name and second is the data to pass to child controller.
When I click button it will broadcast event and in ChildController $scope.$on function which is always listining to the ParentController events. First parameter of "$on" is the event name which will be same as the propagated event name from ParentController. Second parameter is a callback function and first parameter of callback contains event details and second parameter is data which passed from ParentController. When you click button your output will be as below,
$scope.$emit
$scope.$emit works exactly opposite to $scope.$broadcast, it means $scope.$emits propagates event from child to parent. I am reusing the same example with minor modification to add $scope.$emit . See sample below,
eventModule.controller('ParentController', function ($scope) {
$scope.$on("sampleEvent", function (event, data) {
$scope.ParentData = "Message from child controller: " + data;
});
});
eventModule.controller("ChildController", function ($scope) {
$scope.ChildData = "Yeah I am dare to fail";
$scope.SendMessageToParent = function () {
$scope.$emit("sampleEvent",
$scope.ChildData);
}
});
and view,
<html ng-app="eventModule">
<head>
<title></title>
</head>
<body>
<div ng-controller="ParentController">
Parent Controller : {{ParentData}}
<br />
<div ng-controller="ChildController">
Child Controller : {{ChildData}}
<br />
<input type="button" value="BroadCastEventToParent" ng-click="SendMessageToParent()" />
</div>
</div>
<script src="Scripts/AngularJS/angular.min.js"></script>
<script src="Scripts/Module/EventModule.js"></script>
<script src="Scripts/Controllers/ParentController.js"></script>
<script src="Scripts/Controllers/ChildController.js"></script>
</body>
</html>
Now after click button will be as below,
Now after click button will be as below,
Now everything is self explanatory isn't it?? It works exactly opposite to $broadcast, emits event from child to parent.
There is issue with $scope.$broadcast and $scope.event, it works only with immediate parent child relationship. Then how to we can propagates events in all hierarchy? Well that is where $rootScope comes to picture. $rootScope is the base. In other way all $scope inherits from $rootScope.
The $rootScope Object has the identical $emit, $broadcast, $on methods, but they work slightly differently to how $scope implements them. As $rootScope has no $parent, using an $emit would be pointless, right? Nope, instead, $rootScope.$emit will fire an event for all $rootScope.$on listeners only. The interesting part is that $rootScope.$broadcast will notify all $rootScope.$on as well as$scope.$on listeners.
The $rootScope Object has the identical $emit, $broadcast, $on methods, but they work slightly differently to how $scope implements them. As $rootScope has no $parent, using an $emit would be pointless, right? Nope, instead, $rootScope.$emit will fire an event for all $rootScope.$on listeners only. The interesting part is that $rootScope.$broadcast will notify all $rootScope.$on as well as$scope.$on listeners.
I am leaving that you to do work out on $rootScopes $emit, $broadcast, $on services as it is exactly same as above examples but $rootScope will fire events in all hierarchy.
No comments:
Post a Comment