What is .$on() in AngularJS
AngularjsAngularjs Problem Overview
I got this code $rootScope.$on('abc',function(event, next, current){ });
in a tutorial.
My question is what is .$on()
? If it is a function, then why is it preceded by $
?
Angularjs Solutions
Solution 1 - Angularjs
$on
is related to $broadcast
and $emit
- which is a way to trigger code from other places.
The first thing about $on
you should know is that it's a method of $scope
The second thing you should know is $ prefix refers to an Angular Method, $$ prefixes refers to angular methods that you should avoid using.
Now lets get into detail about what $on
is.
Below is an example template and its controllers, we'll explore how $broadcast/$on
can help us achieve what we want.
<div ng-controller="FirstCtrl">
<input ng-model="name"/>
<button ng-click="register()">Register </button>
</div>
<div ng-controller="SecondCtrl">
Registered Name: <input ng-model="name"/>
</div>
The controllers are
app.controller('FirstCtrl', function($scope){
$scope.register = function(){
}
});
app.controller('SecondCtrl', function($scope){
});
My question to you is how do you pass the name to the second controller when a user clicks register? You may come up with multiple solutions but the one we're going to use is using $broadcast and $on.
$broadcast vs $emit
Which should we use? $broadcast will channel down to all the children dom elements and $emit will channel the opposite direction to all the ancestor dom elements.
The best way to avoid deciding between $emit or $broadcast is to channel from the $rootScope and use $broadcast to all its children. Which makes our case much easier since our dom elements are siblings.
Adding $rootScope and lets $broadcast
app.controller('FirstCtrl', function($rootScope, $scope){
$scope.register = function(){
$rootScope.$broadcast('BOOM!', $scope.name)
}
});
Note we added $rootScope and now we're using $broadcast(broadcastName, arguments). For broadcastName, we want to give it a unique name so we can catch that name in our secondCtrl. I've chosen BOOM! just for fun. The second arguments 'arguments' allows us to pass values to the listeners.
Receiving our broadcast
In our second controller, we need to set up code to listen to our broadcast
app.controller('SecondCtrl', function($scope){
$scope.$on('BOOM!', function(events, args){
console.log(args);
$scope.name = args; //now we've registered!
})
});
It's really that simple. Live Example
Other ways to achieve similar results
Try to avoid using this suite of methods as it is neither efficient nor easy to maintain but it's a simple way to fix issues you might have.
You can usually do the same thing by using a service or by simplifying your controllers. We won't discuss this in detail but I thought I'd just mention it for completeness.
Lastly, keep in mind a really useful broadcast to listen to is '$destroy' again you can see the $ means it's a method or object created by the vendor codes. Anyways $destroy is broadcasted when a controller gets destroyed, you may want to listen to this to know when your controller is removed.
Solution 2 - Angularjs
The previous answer is a very good one. I'd like only to add a short remark: this $on kind of listener has a very important property: can be canceled (stoped). I'll explain what do I mean:
The html:
<div ng-controller="FirstCtrl">
<input ng-model="name"/>
<button ng-click="register()">Register </button>
</div>
<div ng-controller="SecondCtrl">
Registered Name: <input ng-model="name"/>
</div>
<hr/><br/>
<button ng-click="disableEvents()">Disable events</button>
And the controller:
app.controller('SecondCtrl', function($scope){
$scope.cancelOn = $scope.$on('BOOM!', function(events, args){
console.log(args);
$scope.name = args; //now we've registered!
});
// this will cancel the event listening....
$scope.disableEvents = function(){
console.log('Canceling the event listener: ', $scope.cancelOn());
}
});
If you press the "Register" button, you can see it communicate with the second controller. Now press the "Disable events" button. This will cancel the listener, the $on(...). Now, if you press again the "Register", you'll notice that the listener is no longer listen for this kind of event.