What is .$on() in AngularJS

Angularjs

Angularjs 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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser720445View Question on Stackoverflow
Solution 1 - Angularjsyangli-ioView Answer on Stackoverflow
Solution 2 - AngularjsZelter AdyView Answer on Stackoverflow