user880386
user880386

Reputation: 2827

AngularJs: to Propagate event between directives by $emit

I have under one controller two directives :

<div ng-controller="ctrl">
   <div data-dy-items-list items="items"></div>           // FIRST DIRECTIVE
   <div data-dy-subitems-list subitems="subitems"></div>  //SECON DIRECTIVE
</div>

In the Second directive template, I have one button and in the directive.js file in the controller section I did this :

$scope.clickButton= function () {
 ......
$scope.$emit("UPDATE_PARENT","updated");

}

In the first directive, I would like to do this in the controller section:

$scope.update = false;
    $scope.$on("UPDATE_PARENT", function (event,message){
                    $scope.update = true;
                    console.log('update: ' + $scope.update);
                });

But it doesn't work!!!

Upvotes: 3

Views: 7946

Answers (2)

Michał Miszczyszyn
Michał Miszczyszyn

Reputation: 12721

$emit dispatches an event upwards through the scope hierarchy. Your directives are siblings and thus $emit won't work.

The solution might be to $broadcast an event from a parent scope. Do it from ctrl if that's an option for you, or inject $rootScope to the directive and do $rootScope.$broadcast from there:

$rootScope.$brodcast("UPDATE_PARENT","updated");

Mind that $broadcasting events from $rootScope might seem to be an anti-pattern for AngularJS. It strongly depends on the usecase. There are other solutions to your problem:

  • One of them is to create a parent directive for both of your directives.
  • Another one is to use an intermediatory service which will hold values. Then you can do $watch on the service data and react accordingly.
  • You can $emit the event to the ctrl and then ctrl will $broadcast it down to the other directive.

Choose whatever fits your needs best.

Upvotes: 7

Dmitri Algazin
Dmitri Algazin

Reputation: 3456

I just got same problem.

Event between two directives was now passed, not with scope.$emit, not with scope.$broadcast.

After looking around, I did this trick, Use scope.$parent.$broadcast with your $parent scope:

Directive 1:

scope.$parent.$broadcast('NO_LIVE_CONNECTION', {});

Directive 2:

scope.$on('NO_LIVE_CONNECTION', function (event, params) {
  console.log("No live DB connections ...");
  scope.state.showErrorMessage = true;
});

Upvotes: 2

Related Questions