Question

The problem occurs when I try to send an event from my directive to a nested directive via the $scope object. E.g. $scope.broadcast('event') the child directive doesn't receive the event, but when I use the $rootScope object it works e.g. $rootScope.broadcast('event').

TL;DR: Why doesn't this work: http://plnkr.co/edit/27qYiHOilpVABSwMI0Fb?p=preview when this works: http://plnkr.co/edit/o91yFKnQzHp7edUTTkJE?p=preview

EDIT: In angular.js version 1.3.0 and up this is no longer a issue!!!

Was it helpful?

Solution

Your directive(s) uses ng-transclude. From the docs:

In a typical setup the widget creates an isolate scope, but the transclusion is not a child, but a sibling of the isolate scope.

This is what your scope hierarchy looks like:

Scope hierarchy

  • 003 is the isolated scope of directive one
  • 004 is the transclusion scope where the two elements live in
  • 005 is the scope of the first directive two
  • 006 is the transclusion scope of the first directive two

So as you can see the scope of two is not a child scope of one.

OTHER TIPS

Transclusion creates an 'isolate' scope, but the transclusion is not a child, but a sibling of the 'isolate' scope.

(From the source code)

There is no parent <-> child relationship. Therefore $broadcast, $emit won't work because $broadcast requires children and $emit requires a parent that you think is a sibling.

There are a lot of great explanations for the problem here that have probably encouraged you to rethink the way your controllers are organized, as well as how you are using ng-transclude. In case you want another solution, I wrote a tiny directive that solves the interaction between two directives to create the parent <-> child hierarchy. Use at your own risk and I hope this helps! :)

https://gist.github.com/meanJim/1c3339bde5cbeac6417d

It's because you gave the directives isolate scope. Remove the scope parameter from the directive if you want it to have nested scope with parent elements. Or you can define on the scope the properties and values from the parent scope that you would like to pass to the directive's scope.

http://plnkr.co/edit/aMEpo5zZ76rfMj7Khnoy?p=preview

If the scope of FirstCtrl is parent to the scope of SecondCtrl, you should use $broadcast method in the FirstCtrl:

'use strict';
angular.module('myAppControllers', [])
  .controller('FirstCtrl', function ($scope) {
    $scope.$broadcast('UPDATE_CHILD');
  })
  .controller('SecondCtrl', function ($scope) {
    $scope.$on('UPDATE_CHILD', function() {
      // do something useful here;
    });
  });

if there’s no parent/child relation between scopes, you should inject $rootScope into the FirstCtrl and broadcast the event into other controllers (including SecondCtrl) and their corresponding (child in this case) $scope’s:

'use strict';
angular.module('myAppControllers', [])
  .controller('FirstCtrl', function ($rootScope) {
    $rootScope.$broadcast('UPDATE_ALL');
  });
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top