Basically, there are two ways of handling the communication between controllers in AngularJS:
- using a service which acts as a PubSub/Event bus when injected into controllers:
- code example (John Lindquist’s fantastic webcast can be found here):
'use strict'; angular.module('myAppServices', []) .factory('EventBus', function () { return {message: "I'm data from EventBus service"} });
'use strict'; angular.module('myAppControllers', ['myAppServices']) .controller('FirstCtrl', function ($scope, EventBus) { $scope.data = EventBus; }) .controller('SecondCtrl', function ($scope, EventBus) { $scope.data = EventBus; });
- code example (John Lindquist’s fantastic webcast can be found here):
- note:
In case you don’t need a controller anymore on your page, there’s no way (other than manual) to automatically “unsubscribe” such controllers (as of today AngularJS doesn’t support component life-cycle hooks, by the use of which you could wire/un-wire components). This is because of closures used in controllers that are not “de-allocated” (memory) when the function returns. As a result, you’ll be still sending messages to such “unused” controllers.
- depending on the parent/child relation between scopes, you can transmit events using either $broadcast or $emit methods:
- if the scope of FirstCtrl is parent to the scope of SecondCtrl, you should use $broadcast method in the FirstCtrl:
'use strict'; angular.module('myAppControllers', []) .controller('FirstCtrl', function ($scope) { $scope.$broadcast('UPDATE_CHILD'); }) .controller('SecondCtrl', function ($scope) { $scope.$on('UPDATE_CHILD', function() { // do something useful here; }); });
- if the scope of FirstCtrl is parent to the scope of SecondCtrl, you should use $broadcast method in the FirstCtrl:
- if there’s no parent/child relation between scopes, you should inject $rootScope into the FirstCtrl and broadcast the event into other controllers (including SecondCtrl) and their corresponding (child in this case) $scope’s:
'use strict'; angular.module('myAppControllers', []) .controller('FirstCtrl', function ($rootScope) { $rootScope.$broadcast('UPDATE_ALL'); });
- finally, when you need to dispatch the event from a child controller (SecondCtrl) to $scope’s upwards , you should use the $emit method:
'use strict'; angular.module('myAppControllers', []) .controller('FirstCtrl', function ($scope) { $scope.$on('UPDATE_PARENT', function() { // do something useful here; }); }) .controller('SecondCtrl', function ($scope) { $scope.$emit('UPDATE_PARENT'); });
- note:
because $broadcast will dispatch events downwards through (all) scope’s hierarchy, it results in a slight performance hit (more details and performance tests results, here).
Cheers!
Resources:
- Egghead.io webcast by John Lindquist (http://egghead.io/lessons/angularjs-sharing-data-between-controllers)
- $rootScope.emit() vs $rootScope.$broadcast, performance tests (http://jsperf.com/rootscope-emit-vs-rootscope-broadcast)
- One Hungry Mind webcast (http://onehungrymind.com/angularjs-communicating-between-controllers)
Tagged: AngularJS, JavaScript
[…] https://mariuszprzydatek.com/2013/12/28/sharing-data-between-controllers-in-angularjs-pubsub-event-bu… […]
http://blog.logiticks.com/communication-between-controllers-in-angularjs-emitonbroadcast/