4
votes

In this PlunkerDemo, I'm trying to broadcast an event from the parent controller to child controller. However doing it directly in the parent controller won't work. The handler doesn't register the event. However doing it based on an ng-click or based on setTimeout, it works. Is it due to the scope life cycle?

http://beta.plnkr.co/edit/ZU0XNK?p=preview

See the comments of the accepted answer. They explain my problem.

2

2 Answers

17
votes

Any changes to angular scope must happen within the angular framework, If any changes have to be made outside the framework we have to use the .$apply function.

$apply() is used to execute an expression in angular from outside of the angular framework.

In your case you are triggering the $broadcast within setTimeout, where the callback gets called outside the angular framework.

So you have two solutions, either use the $timeout service provided by angular or use .$apply function.

I prefer to use the $timeout function.

var ParentCtrl = function($scope, $rootScope, $timeout){

    $scope.broadcast = function(){
        $rootScope.$broadcast('Sup', 'Here is a parameter');
    };

    $timeout(function(){
        $scope.$broadcast('Sup');
    }, 1000);

    //this one does not work! Most likely due to scope life cycle
    $scope.$broadcast('Sup');

    $scope.$on('SupAgain', function(){
        console.log('SupAgain got handled!');
    });

};

Demo: Fiddle

Using $apply

setTimeout(function(){
    $scope.$apply(function(){
        $scope.$broadcast('Sup');
    });
}, 1000);
0
votes

A more reliable option can be to use $interval in child controller. So, instead of having significant timeout, there will be polling every small interval. Also, instead of broadcast, use a service with a flag. Every poll will check if flag is set. When the flag is set by parent controller, the timer will be stopped during next poll. And that can indicate the event happened. The parent controller can also share data with child controller, via service.