Broadcasting events between controllers
Broadcasting events between controllers
There can be multiple situations where you may want a controller to be able to communicate with other controllers in your AngularJs Application. For example, you want your user to be able to click a button and for another controller to be aware of the UI change; one solution is to broadcast events to the controllers. Consider the following example:
Consider a User details page where the user must fill out multiple sections. However, some sections are disabled until the user controller creates a user identifier. Once it is created, the user controller will broadcast an event to other user details controllers, enabling user detail sections that had been disabled earlier.
Let us see the broadcast event method of controller communication with another example. Here, we have two separate controllers "VoteCounterController," in which we store the current vote count in the controller scope, and “VoteRegisteredController,” which communicates with “VoteCounterController” to update the number of votes every time a voter clicks the vote button.
HTML
<div ng-app="app"> <div ng-controller="VoteCounterController"> The current vote count is: </div> <div ng-controller="VoteRegisteredController"> <button ng-click="voteHereClicked()">Vote Here</button> </div> </div>
Here is what our controllers look like
var app = angular.module(app, []); app.controller(VoteCounterController, ['$scope', function ($scope) { $scope. voteCount = 1; }]); app.controller(VoteRegisteredController, ['$scope', function ($scope) { $scope. countVote = function () { console.log(Vote counted successfully); }; }]);
Currently, there is no link between the two controllers as they are not referencing each other in any way. In most cases, controllers only interact with each other for a few events, and referencing is not needed. However, in this case, they are completely unaware of each other's existence.
Let's modify the controllers so that they can communicate with each other:
app.controller(VoteCounterController, ['$scope', '$rootScope', function ($scope, $rootScope) { $scope. voteCount = 1; $rootScope.$on(countVote, function () { $scope. voteCount ++; }); }]);
We first modify the VoteCounterController to listen for an event generated by the VoteRegisteredController. AngularJs allows listening to and broadcasting events on any defined module.
Using the $rootScope variable and the $on method, we can listen for any events broadcast to the $rootScope.
Now that we have the listener setup let’s broadcast the event we need:
Let's update the VoteRegisteredController to broadcast an event when clicking the vote button. Again, this will need to be done on the $rootScope variable.
app.controller(VoteRegisteredController, ['$scope', '$rootScope', function ($scope, $rootScope) { $scope. voteHereClicked = function () { $rootScope.$broadcast(countVote); }; }]);
Now, you can see that even though both controllers are not referencing each other, they are still communicating to count the votes through an event broadcast.
As a final step, it's a good practice to destroy the event afterward:
We can destroy the broadcasted event after its scope ends.
In order to do this, we need to modify our First Controller as follows –
app.controller(VoteCounterController, ['$scope', '$rootScope', function ($scope, $rootScope) { $scope. voteCount = 1; var increamentCountVote = $rootScope.$on(countVote, function () { $scope. voteCount ++; }); $scope.$on('$destroy', function() { if(increamentCountVote ) { increamentCountVote (); } }); }]);
Downside
Overuse of the event broadcasting method may cause some performance issues.
Conclusion
We have shown an example of how two different controllers can interact with each other for an event to perform tasks by broadcasting the events on root scope. We also showed how it is good practice to destroy these events once the scope ends. Broadcasting is a good way to pass an event downwards a tree hierarchy, from parent scopes to child scopes. Event broadcasts help lessen the dependence on using the global $rootScope to communicate and make the code more modular and easy to test.