Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

$broadcast event not received by controller

So I have an angularjs app with several partial views and one controller per partial view. I also have a service which will $broadcast events from the $rootScope:

$rootScope.$broadcast('MyEvent', 'message');

Currently there is only one controller listening for events and I noticed that if I am not on the view that is associated to that one controller (via routes), then the event is never received in that controller and thus never loads the view associated to it. How can I ensure that the controller receives the event broadcast regardless of which view is active? I tried using $scope.$on('MyEvent')... and $rootScope.$on('MyEvent')... in my controller; neither seem to work.

like image 411
user1491636 Avatar asked Jul 28 '14 15:07

user1491636


2 Answers

This is the expected behavior, as your partial views have individual controllers associated with them. The controller would be in scope only if the view is rendered.The controller comes in to scope only when your ng-controller directive is parsed in your partial view.So expect your controllers to be in scope only after loading the view associated with it.

In your case, when you broadcasted the event myEvent using $rootScope.$broadcast('MyEvent', 'message'); the controller you wanted to receive this event was not in scope.

to see this clearly put a breakpoint on your broadcast step and pause the execution to check the value of angular.element('[ng-controller=urControllerName]').scope() in console and you can see that it would be undefined meaning that the controller is not yet in scope.

like image 113
Divya MV Avatar answered Sep 20 '22 21:09

Divya MV


It would help if you included a bit more of your code because there's a right way and a wrong way to do an $on(), and your shorthand would be the wrong way. I saw somebody once who thought this returned a promise and was trying to use .then() on it, and that won't work. It takes a callback:

$rootScope.$on('MyEvent', function(myParam) {
    alert(myParam);
});

Separately, if you're doing pub/sub type work pay attention to the different between $emit and $broadcast. It's important for efficiency reasons, and if you don't need to actually use $broadcast you might want to reconsider it. $broadcast will send the message on that scope plus all child scopes. That means Angular needs to iterate recursively through every scope ever made to look for listeners for the event. If you use a lot of directives (many of those have scopy) and ngRepeats, you could have thousands of these!

Typically you use $broadcast when you want to put something out within a specific scope and its children deliberately, like when you're posting events between siblings in a data table row or something like that. (Hover effects, data updates to the row, that kind of thing...)

What you can do instead is use $emit. This works the same way (you still use $on to listen for it) but this time it goes up the scope chain. That means if you start it on $rootScope it will just hit one quick list of listeners and stop there - it's extremely fast and efficient if you're registering your $on() events at the same level. In that case you would use $rootScope.$on() instead of $scope.$on()... but the efficiency gain is worth it!

like image 45
Chad Robinson Avatar answered Sep 21 '22 21:09

Chad Robinson