-
-
Save turtlemonvh/10686980 to your computer and use it in GitHub Desktop.
var MyApp = angular.module('MyApp'); | |
MyApp.factory('msgBus', ['$rootScope', function($rootScope) { | |
var msgBus = {}; | |
msgBus.emitMsg = function(msg, data) { | |
data = data || {}; | |
$rootScope.$emit(msg, data); | |
}; | |
msgBus.onMsg = function(msg, func, scope) { | |
var unbind = $rootScope.$on(msg, func); | |
if (scope) { | |
scope.$on('$destroy', unbind); | |
} | |
return unbind; | |
}; | |
return msgBus; | |
}]); |
Example of use
Binding in a controller
// Passing in $scope allows the service to clean up references for you automatically
msgBus.onMsg('config.changed', function(event, data) {
$scope.power = data.power;
$scope.mass = data.mass;
}, $scope);
Binding in a service
// You can call unbindItemRemoved to clear the reference to this service
// and prevent memory leaks
var unbindItemremoved = msgBus.onMsg('config.itemRemoved', respondToChangeInItems);
Emitting in a controller or a service
msgBus.emitMsg('config.itemAdded', {'id': getID()});
Thank you!
+1
Thanks! :)
This is just what I needed. Thanks for sharing!
In case other's stumble upon this small issue, the function you register with the msgBus.onMsg() function can takes a 'scope' argument. However, you cannot access that argument within the function defined because the call to $rootScope.$emit() doesn't pass anything for a third argument (for obvious reasons). Therefore, if you want to access the scope variable, you'll have to make a separate reference to it for use within the callback function.
app.directiive(....) {
...
link: function(scope, element, attrs) {
var linkScope = scope;
msgBus.onMsg('msg-to-watch', function(event, data, scope) {
//scope.whatever; <-- will return undefined
linkScope.whatever; // <-- accessible
}
}
}
Thanks! for many searching , this is the best solution
This is how we approached this, basically we replaced the $rootScope.$on function with another that maintains the same functionality, but if it takes a third parameters (scope), it will attach a destroy event to it that automatically removed the rootScope event.
app.run(["$rootScope", function($rootScope) {
var _nop = function() {};
var _ref = $rootScope.$on;
$rootScope.$on = function(name, listener, scope) {
var unbind = _ref.call($rootScope, name, listener);
if(scope && unbind) {
scope.$on('$destroy', unbind);
return _nop;
}
return unbind;
}
}]);
thanks,very helpful
An edit of this answer on StackOverflow about the best way to do message passing in angular.
I extended the solution to:
unbind
function so the user can do their own memory management