Working With $Scope.$Emit and $Scope.$On

Implement a single method or use $scope.on and $scope.emit in AngularJs that will call the same method in multiple controllers without a service

The the $on functions with same name will get called with its corresponding single $emit call. I mean, you have multiple $on functions in multiple controllers,

$scope.$on('funtionToTrigger', function(event, args) {
//in first controller
});

$scope.$on('funtionToTrigger', function(event, args) {
//in second controller
});

$scope.$on('funtionToTrigger', function(event, args) {
//in third controller
});

Note: all $on functions' name are same 'funtionToTrigger'.
Once you call $scope.$emit('funtionToTrigger', args); then all three $on functions will run in all three controllers.

So here, you have write a $on function in each controller.

function SocialMentionsAnalysisController () {
$scope.$on('funtionToTrigger', function(event, dateFrom, dateTo) {
//your code for this controller.
});
}

function SocialMentionsListController() {
$scope.$on('funtionToTrigger', function(event, dateFrom, dateTo) {
//your code for this controller.
});
}

Then call $emit on onChange.

ng-change="$emit('funtionToTrigger', dateFrom, dateTo)"

pass data between components with $scope.$emit()

You need to broadcast to the child's parent:

$scope.$parent.$broadcast('hi', {
msg: 'Hello there!'
});

$scope.$broadcast sends the message down the chain, but if you broadcast to the scope's parent then the parent will send the message down, which includes both siblings.

angular.module('appModule', [])

.controller('ParentController', [function() {

this.hello = 'I am the parent';

}])

.controller('Child1Controller', ['$scope', function($scope) {

this.hello = 'I am Child 1';

var that = this;

$scope.$on('hi', function(event, data) {

console.log(data.msg);

that.hello = data.msg;

});

}])

.controller('Child2Controller', ['$scope', function($scope) {

this.hello = 'I am Child 2';

this.sayHello = function(str) {

$scope.$parent.$broadcast('hi', {

msg: str

});

}

}]);

angular.bootstrap(window.document, ['appModule'], {

strictDi: true

});
div {

border: 1px dotted #f00;

padding: 15px;

}
<div ng-controller="ParentController as parentCtrl">

<p>{{parentCtrl.hello}}</p>

<div ng-controller="Child1Controller as child1Ctrl">

<p>{{child1Ctrl.hello}}</p>

</div>

<div ng-controller="Child2Controller as child2Ctrl">

<p>{{child2Ctrl.hello}}</p>

<button type="button>" ng-click="child2Ctrl.sayHello('Child 2 is cool')">Say Hello to Child 1</button>

</div>

</div>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.7/angular.min.js"></script>

Usage of $broadcast(), $emit() And $on() in AngularJS

$emit

It dispatches an event name upwards through the scope hierarchy and notify to the registered $rootScope.Scope listeners. The event life cycle starts at the scope on which $emit was called. The event traverses upwards toward the root scope and calls all registered listeners along the way. The event will stop propagating if one of the listeners cancels it.

$broadcast

It dispatches an event name downwards to all child scopes (and their children) and notify to the registered $rootScope.Scope listeners. The event life cycle starts at the scope on which $broadcast was called. All listeners for the event on this scope get notified. Afterwards, the event traverses downwards toward the child scopes and calls all registered listeners along the way. The event cannot be canceled.

$on

It listen on events of a given type. It can catch the event dispatched by $broadcast and $emit.


Visual demo:

Demo working code, visually showing scope tree (parent/child relationship):

http://plnkr.co/edit/am6IDw?p=preview

Demonstrates the method calls:

  $scope.$on('eventEmitedName', function(event, data) ...
$scope.broadcastEvent
$scope.emitEvent

Difference between $rootScope.$on vs $scope.$on

This is a good questions and there is an explanation for you.

First of all note that:

  • $scope.on('event'); will listen to $scope.$broadcast('event') & $rootScope.$broadcast('event')

  • $rootScope.on('event'); will listen to $rootScope.$broadcast('event') & $rootScope.$emit('event')

Next you need to note that:

  • $scope.on(); will be destroyed automatically when the controller loses it representation in view or component (getting destroyed).
  • You need to destroy $rootScope.$on() manually.

>> Example of how to destroy $rootScope.on():

//bind event
var registerScope = $rootScope.$on('someEvent', function(event) {
console.log("fired");
});

// auto clean up `$rootScope` listener when controller getting destroy
// listeners will be destroyed by calling the returned function like registerScope();
$scope.$on('$destroy', registerScope);

>>> Since Angular v1.5 we can use component lifecycle to manage init and destroys in a nice way:

var myApp = angular.module('myApp',[]);

myApp.controller('MyCtrl', function ($scope, $rootScope) {

var registerScope = null;

this.$onInit = function () {
//register rootScope event
registerScope = $rootScope.$on('someEvent', function(event) {
console.log("fired");
});
}

this.$onDestroy = function () {
//unregister rootScope event by calling the return function
registerScope();
}
});

This plnkr will show you the different behaviors of $scope.on() and $rootScope.on().

By switching the view in this plunkr the controller will be rebinded to your view. The $rootScope.on(); event is binded every time you switch a view without destroying the event bindings of the view before. In that way the $rootScope.on() listeners will be stacked/multiplied. This will not happen to the $scope.on() bindings because it will be destroyed by switching the view (losing the E2E binding representation in DOM -> controller is destroyed).

The difference between $emit & $broadcast is:

  • $rootScope.$emit() events only triggers $rootScope.$on() events.
  • $rootScope.$broadcast() will trigger $rootScope.$on() & $scope.on()events (pretty much everthing hear this event).
  • $scope.$emit() will trigger all $scope.$on, all its parents (scopes in parent controllers) and $rootScope.$on().
  • $scope.$broadcast will only trigger $scope and its children (scopes in child controllers).

Additional Links

  • Do you need to unbind $scope.$on in $scope $destroy event?

Angularjs: $scope.emit is not working

The $emit function propagate an event only to the scopes parents.

The $broadcast function propagate an event to the scopes childs.

So what you need depends on how the controllers are use it...

If you want an event to reach all the app you have to use the $rootScope:

$rootScope.$broadcast('myEvent');

Here you have the doc of the scope, include $emit and $broadcast



Related Topics



Leave a reply



Submit