Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

$emit from child controller works, but $broadcast from parent scope doesn't

When I call $scope.$broadcast none of the events my children are listening to are getting triggered. A simplified example is below:

HTML

Below is a simplified example of what I'm trying to accomplish:

<div ng-app="app" ng-controller="parentCtrl">
  <div ng-controller="childCtrl">
    <b>Parent Event:</b> {{outer}}<br />
    <b>Child Event:</b> {{inner}}<br />
  </div>
</div>

AngularJs

mc = angular.module('app', [
  'app.controllers',
]);

angular.module('app.controllers', [])
    .controller('parentCtrl', ['$scope', '$http', '$q', function ($scope, $http, $q) {
        $scope.outer = 'not executed';
        $scope.$broadcast('EventFromParent');
        $scope.$on('EventFromChild', function () { 
          $scope.outer = 'executed';
        });        
    }])
    .controller('childCtrl', ['$scope', '$http', function ($scope, $http) {
        $scope.inner = 'not executed';
        $scope.$on('EventFromParent', function () { 
          $scope.inner = 'executed';
        });
        $scope.$emit('EventFromChild');
    }]);

Output

I expect to see triggered for both Parent and Child, but I don't get triggered for Child.

EXPECTED                      ACTUAL
------                        ------
Parent Event: triggered       Parent Event: triggered
Child Event: triggered        Child Event: not triggered

Theory

My guess here is that the child controller is not ready to receive events. That I need to wait until the DOM is ready, but I don't see how to do that with Angular. Feel free to tell me that this is just the wrong way to go about what I'm doing too.

Plunkr

like image 785
Daniel Gimenez Avatar asked Mar 11 '14 13:03

Daniel Gimenez


1 Answers

The problem is $scope.$broadcast in parent controller is called before $scope.$on in child controller, so there is no listeners for this event at the time when the 'EventFromParent' is broadcasted to child scope.

You need to register event listeners before broadcasting or emitting an event. In your case, one way to achieve that is to use $timeout:

$timeout(function() {
    $scope.$broadcast('EventFromParent');
});

(You will need to inject $timeout service first)

This way, you have effectively delayed the event broadcasting, and the event listener has got chance to register itself, so when the event happens, the listener will be called.

like image 157
Ye Liu Avatar answered Sep 23 '22 09:09

Ye Liu