0

I would like to notify multiple controllers of external changes from a service. I know that i can do this by using a deferred object and calling notify on it and registering a callback on that.

e.g

// in service
        $timeout(function() {
                defered.notify('In progress')}
            , 0)

//in controller
    var promise = myService.promise
    promise.then(function(success) {
        console.log("success");
    }, function(error) {
        console.log("error");
    }, function(update) {
        console.log("got an update!");
    }) ;

Is there a way to remove my notify callback when the controller is destroyed?

TJF
  • 1,081
  • 1
  • 12
  • 26

2 Answers2

3

EDIT DUE TO FURTHER QUESTION DETAILS

You could cancel the $timeout when you destroy the controller:

Create the $timeout as so...

$scope.myTimeout = $timeout(function() {
                defered.notify('In progress')}
            , 0);

In the controller add this:

$scope.$on('$destroy', function () {
    $timeout.cancel($scope.myTimeout);
});

In my experience this appears to clean everything up.

To clear just the notify callback itself, use the suggested $broadcast, $emit(see @Pio's answer) A guide to the difference between them is here.

Its important to know the difference!

AMadmanTriumphs
  • 4,888
  • 3
  • 28
  • 44
  • I just want to delete the individual notify callback from the controller as there could be many of them – TJF Jan 21 '15 at 11:16
  • 1
    Well in that case, I'd be tempted to use events ($broadcast, $emit etc) but be careful as you must understand the difference when using them! – AMadmanTriumphs Jan 21 '15 at 11:18
  • 1
    Do you need to unregister to $on in the controller when it is destroyed? – TJF Jan 21 '15 at 11:22
  • 1
    The guide I linked it should explain, I don't think you need too as I think its automatic, but others might know better! – AMadmanTriumphs Jan 21 '15 at 11:24
  • 2
    @user1168234 - had a quick look, if the scope is in a controller then angular will unregister it for you. Otherwise you can unregister your even by calling the returned function. (i.e. var myevent = $scope.$on('someEvents', handleSomeEvent); myevent(); // unregister the event) – AMadmanTriumphs Jan 21 '15 at 11:31
3

You can use $on, $broadcast and $emit to achieve a similar behavior.

Just $broadcast(name, args); an event and register a listener $on(name, listener);.

So when you got your data you just broadcast to everybody that you've got it.

$broadcast('gotTheData', actualDataObject); 

Then in your controllers

 $on('gotTheData', function(event, actualDataObject)
     {
         ... update controller data ...
      });

Note that in the example I've added only one actualDataObject, but you can pass multiple arguments from the $broadcast to $on. For more details refer to the documentation (see link above).

As per the comments to @Scott's answer you highlighted one important aspect: you need to unregister the $on when you destroy the controller through the "Returns a deregistration function for this listener." (see the docs) at $on returns. There is a question that targets specifically this issue: How can I unregister a broadcast event to rootscope in AngularJS?.

Community
  • 1
  • 1
Pio
  • 4,044
  • 11
  • 46
  • 81