0

What I want is for SubCtrl to broadcast an event when it is loaded saying that it wants to get information. I want MainCtrl to be listening for a call to the get event and respond by broadcasting the 'set' event and providing its name property as an argument. The SubCtrl should be listening for the set event and respond by populating its own scopes name property.

With the following code, MainCtrl receives the get event, but SubCtrl never receives the set event.

Script

app.controller('MainCtrl', function($scope, $rootScope) {
  $scope.name = 'World';
  $scope.$on('get', function(event) {
    console.log('get event received');
    $rootScope.$broadcast('set', $scope.name);
  })
});

app.controller('SubCtrl', function($scope, $rootScope) {
  $scope.name = '..waiting';
  $rootScope.$broadcast('get');
  $scope.$on('set', function(event, name) {
    console.log('set event received');
    $scope.name = name;
  });
});

Markup

<body>
  <p ng-controller="MainCtrl">Hello {{name}}!</p>
  <p ng-controller="SubCtrl">Hello {{name}}!</p>
</body>
km6zla
  • 4,787
  • 2
  • 29
  • 51

2 Answers2

1

Using $rootScope.$broadcast could be performance greedy depending on the size of your app. (See this question for more info.)

If you want to communicate between controllers on sibling nodes, there are 2 ways:

  • use a common parent controller
  • use a shared service.

With my team, we decided to develop a small pub/sub service to solve a similar issue. If you want to try it, here's our angular-pubsub service.

Community
  • 1
  • 1
glepretre
  • 8,154
  • 5
  • 43
  • 57
  • You were completely correct about $broadcast being the wrong way to go. I use a service now as you suggest. +1 for that. The problem was something different but you were right as well. – km6zla Mar 05 '14 at 21:06
0

Once again I immediately realized the problem. I need to set the $on listener before I $broadcast the get event.

app.controller('SubCtrl', function($scope, $rootScope) {
  $scope.name = '..waiting';
  $scope.$on('set', function(event, name) {
    console.log('set event received');
    $scope.name = name;
  });
  $rootScope.$broadcast('get');
});
km6zla
  • 4,787
  • 2
  • 29
  • 51
  • Does it work now? I'm surprised because `$broadcast` should be used to dispatch event to **child scopes** and `$emit` to dispatch to parent scopes (according to [$scope docs](http://docs.angularjs.org/api/ng.$rootScope.Scope)). If you want to communicate between controllers on sibling nodes, there are 2 ways: use a common parent controller or use a service, like a pub/sub service. I chose the second solution. If you want to try it, my angular-pubsub service is here: https://github.com/glepretre/angular-pubsub. – glepretre Feb 13 '14 at 08:19
  • Hey that *is* a good idea! I will check that out. My code does work because I am `$broadcast`-ing from `$rootScope` and listening `$on` the local scope. – km6zla Feb 13 '14 at 17:11
  • I'm glad you like the idea :) I'll add it as an answer for better visibility. Please give me your feedback on the PubSub when you try it ;) – glepretre Feb 13 '14 at 17:35