Skip to content Skip to sidebar Skip to footer

Broadcast Not Received In Directive

I have a parent-child controller relationship between my
,
and as such:

Solution 1:

From the Documentation:

$broadcast(name, args);

Dispatches an event name downwards to all child scopes (and their children) notifying the registered $rootScope.Scope listeners.

As in your directive you are not creating a new scope I guess you are just on the same scope level as your MainController. In this case you are not in a childScope of MainController so the event can't be triggered there. I would try one of the following:

  1. Broadcast your events always via $rootScope.$broadcast. All other scopes are childs of $rootScope and so wherever you register to an event with $scope.$on, you will receive it. You may also be interested in Why do we use $rootScope.$broadcast in AngularJS?

  2. Give your directive an isolated $scope. That will act as a childScope to MainController and should work as well. Isolationg the $scope of a directive.

  3. In addition to option 1. you can also use $rootScope.$emit together with $rootScope.$on. For further information read $rootScope.$broadcast vs. $scope.$emit

I always chose option 1. as sometimes you don't want your directive to have an isolated scope.

Solution 2:

There is a race condition.

myDirective controller and post-link function are executed after MainController, and the listener is set up after shoppingCartReady event has been triggered.

A rule of thumb for good, testable directive design is to keep all scope-related logic in controller, linking functions and $onInit hook are used exactly for the things that should happen there and not anywhere else, like manipulations on compiled DOM content.

Less obvious but distinctive use case for link is the desirable order of execution (post-linking functions are executed in reverse order, from children to parent). If MainController becomes a directive, and scope.$broadcast('shoppingCartReady', msg) is executed in link function and not controller, this guarantees the proper order of execution.

Wrapping controller code into zero $timeout will also postpone the code

$timeout(function(){
    $scope.$broadcast('shoppingCartReady', msg);
});

to be executed after linking functions in children directives, but will also designate some code smell. This is one of the reasons why scope events are less desirable ways of directive communication and are prone to be anti-patterns.

The alternative way of handling this depends on what shoppingCartReady event is about, but in current case it is redundant: it has already happened at the moment when children controllers are executed, they can safely assume that 'shopping cart is ready'.

A suggested reading for this topic: Directive Controller And Link Timing In AngularJS .

Post a Comment for "Broadcast Not Received In Directive"