Overview
AngularJs scope( $scope ) has methods called as $broadcast and $emit which makes it very easy to send messages and data from one controller to different controllers up or down in the scope hierarchy .
say if ? controller A ? is waiting for a response from an REST API , So now it can trigger an event and send message to the controllers which are down or up in its scope hierarchy and notify them that the request is pending / success / failure . Now the controllers which are listening to the event triggered by ? controller A? can do further actions based on the event and data ( state ) received from ? controller A?.
Thus these methods are used to make different parts of your application to talk to each other , thus a fluent conversation can ultimately be had with your user.
However please don?t think these methods should be used to share the $scope models from one controller to another, we normally share $scope model ( data ) among controllers using services or factories, that?s a whole different story;)
I know some of you guys still might in a zombie state , but I would like to say ? JUST CHILL GUYS ? its just the overview lets move to Big Picture to understand it much better.
Big Picture
$broadcast and $emit method internally uses publish-subscribe pattern paradigm to make different parts of an AngularJs application to talk to each other.
Publish-Subscribe Pattern paradigm works in a three steps :1) Trigger event 2) listen to event 3) act on the event .
The above three steps are also adapted by angular to achieve communication between different components.
Trigger Event : Event is triggered by the controller using $broadcast( ) or $emit( ) functions to send message across the scope hierarchy ( upwards or downwards )
Listen to the event : When an event is broadcasted or emitted , controllers can listen to that specific event using $on( ) method .
Act on the Event : The $on( ) method does what it want with the event and data which it receives from the triggered event.
How to Trigger an Event ( $broadcast & $emit )
An event can be triggered downwards and upwards in the scope hierarchy
HOW A BROADCASTING AN EVENT LOOKS ( Triggers Downwards )
$scope.$broadcast(‘serviceStatus’, {message: ‘Service Failed!’});
In this case, we will be broadcasting an event called serviceStatus with a data object which contains a message.
broadcast ( $broadcast ) triggers an event ( sends data / information / message ) to all its child controllers down in its scope hierarchy all the way to last-child.
a possible depiction of how broadcasting works across the scope
HOW EMITTING AN EVENT LOOKS LIKE ( Triggers Upwards )
$scope.$emit(‘myAPIstatus’, {message: ‘Service success!’});
In this case, we will be emitting an event called myAPIstatus. Looks very similar, right? Well, that?s because both broadcast and emit fire events but differ in the direction in which they?re sent.
emitting ( $emit ) triggers an event ( sends / information / message ) to the controllers up in its scope hierarchy all the way up to the $rootScope! until we don?t stop it explicitly.
a possible depiction of how emit works across the scope
How to Listen to an event ( $on )
An event triggered via Broadcasting or emitting can be listened by the controllers Descending / preceding it.
HOW LISTENING AND ACTING TO AN EVENT LOOKS LIKE
$scope.$on(‘myAPIstatus’, function(event, data){ // do what you want with the data from the event})
In this case, we will be listening to an event called myAPIstatus as soon as it is triggered the callback function gets executed .
a possible depiction of how Listening works across the scope
Practical Example of $broadcast , $emit and $on
Lets Wrap this concept with an example for you guys to get hold of it clearly .
Consider an objective that the moment you click the button present in controller_1 you have to enable the buttons present in controller_2 and controller_3 ( Which are disabled initially ) and also at the same time notify Controller_1 that the event has been listened by and acted up by controller_2 and controller_3
The End result is something like this Pen that I am attaching below
( Note : Please keep the above Pen open in new tab so that you can easily understand what I am saying further )
Lets look at how we have achieved the above objective using $broadcast, $emit an $on.
Controller Hierarchy with respect to HTML
Main Points
1 ) The above code has a Parent Controller called as ?cntrl_1? which has two child’s ?cntrl_2? and ?cntrl_3?.
2 ) The button present inside ?cntrl_1? has an ng-click directive which triggers ?triggerBroadcast? method.
Now we know that $scope.$broadcast( ) allows us to send an event down the controller hierarchy, which means all child controllers of the controller which broadcasts the event will be notified of this event firing. If they are listening to the specific event, you?ll be able to do whatever you?d like with the event data.
So its obvious that we have to have $scope.$broadcast() inside the triggerBroadcast function, so the entire ?cntrl_1? code looks something like this.
Since we are broadcasting ?enable_Btns ? event from cntrl_1, both cntrl_2 and ctrl_3 will be notified given that they are child controllers of one another.
In the above example we have created an event called ?enable_Btns? and broadcast it on a button click. This event should propagate all the way down the controller family and pass event and data object as parameters to the listener functions, In this case $broadcast is sending two properties ?btnEnable? and ?message? as parameter in the object.
In the above code ?btn_status? is a property that is initially set to true ( line no : 2 ) , which will be future utilised by the listener function ( $on ) to set the $rootScope.btn_status variable to ?TRUE? which will intern set the ng-disabled = ?false? to the buttons inside ?cntrl_2? and ?cntrl_3? .
So Let?s add an event listener to cntrl_2 and cntrl_3 so we can display the event message in each one using $on
So the entire ?cntrl_2? and ?cntrl_3? code might look something like below.
in the above code Both ctrl_2 ( line no : 4) and ctrl_3 ( line_no :12) are listening to enable_Btns event, which will come from ctrl1. When that event is broadcasted down, we will display the event data in the respective controller.
The $on ( ) method in ?cntrl_2? and ?cntrl_3? has got object from $broadcast method and now it is assigning it to ?$rootscope.btn_status? and ?$rootscope.btn_status_msg? to change the state of button to true and change the text respectively.
we also know that $scope.$emit( ) allows us to send an event up the controller hierarchy, which means all ancestors controllers ( all the way to rootScope ) will be notified of this event firing. If they are listening to the specific event, you?ll be able to do whatever you?d like with the event data.
we have used $emit inside ?cntrl_3? to notify ?cntrl_1? ( grand parent of cntrl_3 ) that the broadcast has happened and the controllers have listen to the event . The code looks something like this as below.
Once the event is fired ?cntrl_1? will be listening to ?btn_enabled? event and it takes the object from the parameter and changes the text of the button to the message received. The code looks something like this as below.
Above code changes the button text in the ?cntrl_1? to the data object sent from the emit method .
$scope.$broadcast() vs $rootScope.$broadcast()
$broadcast() sends an event to child controller scopes and $emit() sends an event to ancestor controller scopes, now the question is how can sibling controllers act on an event? Angular has a special scope, called $rootScope, which is the single highest ancestor of all scopes in your application ? all scopes are descendants of this scope. This special scope allows us to emit events to sibling controllers since they contain children scopes of the $rootScope.
If you want to all your siblings scopes to get notified about an event then you can use $rootscope something like the example below.
Stop event Propagation in $emit and $broadcast
$emit –
You can cancel the propagation of an emitted event using the events stopPropagation() function. This prevents the event from climbing the controller hierarchy any further.
$broadcast –
Am sorry to say that you cannot stop the propagation of a broadcasted event ? once it?s sent, it?s sent.
Conclusion
Conclusion is that $broadcast() sends an event down the hierarchy of controllers, while $emit() sends an event up the hierarchy. $on() is used to add an event listener to any controller.
Use this pattern when necessary , while sending events across many different controllers can be extremely beneficial, it can quickly become a big mess of events which are being fired but not listened to after iterations on your application.
However please don?t think these methods should be used to share the $scope models from present in one controller to another , we normally share $scope model ( data ) among controllers using services or factories .
If you?re not aware of how scopes are defined and which direction events are sent in , it can be tricky to understand , so my recommendation is that know prototypal hierarchy concept in JavaScript ,because its the best way to understand how $scope works in angular and you can get hold of any topic related to $scope easily in future 🙂
My Recommended Link to know Prototypes and Prototypal Hierarchy in jacascript
Prototypal Inheritance in JavaScript
Last year I wrote a post called ?How to impress me in an interview?, and in it, I mentioned that I run across a lot of?
medium.com
Thanks for Reading ,Please do keep posting comments 😉