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
How to Empty an Array in JavaScript
Listening For Variable Changes in JavaScript
How to Access React Instance (This) Inside Event Handler
Difference Between a Function Expression VS Declaration in JavaScript
How to Get All Properties Values of a JavaScript Object (Without Knowing the Keys)
How to Loop Through a Plain JavaScript Object With the Objects as Members
Async Function Returning Promise, Instead of Value
What Is a Good Regular Expression to Match a Url
Chrome Extension Message Passing: Response Not Sent
Events Triggered by Dynamically Generated Element Are Not Captured by Event Handler
Getting the Id of the Element That Fired an Event
How to Clone an Array of Objects in JavaScript
What's the Difference Between '$(This)' and 'This'
JavaScript: Natural Sort of Alphanumerical Strings
Resolve Promises One After Another (I.E. in Sequence)
Abort Ajax Requests Using Jquery
How to Prevent a Parent'S Onclick Event from Firing When a Child Anchor Is Clicked