psalkowski
psalkowski

Reputation: 414

AngularJS: Broadcast event from parent only to it children

I want to broadcast event from parent directive to child. But if I use scope.broadcast in parent directive link function, then all children in every "parent" directive receive it.

How it works now: If parent (1) broadcast event, then child (1.1) and (2.1) receive event.

How I want it to work: I want to broadcast event from parent (1) only to child (1.1), not child (2.1).

My directive checked if element is on screen. I want only one directive like that and only this directive should send event to others.

<div>
    <div parent> <!-- 1 -->
        <div child></div> <!-- 1.1 -->
    </div>

    <div parent> <!-- 2-->
        <div child></div> <!-- 2.1 -->
    </div>
</div>

Upvotes: 3

Views: 6624

Answers (2)

sbedulin
sbedulin

Reputation: 4332

Probable reason - parent directive shares the same scope, that's why your event is propagated to all child directives.

Solution - each directive should define its own scope, which prototypically inherits from parent. ($root <-- parent <-- child)

<!DOCTYPE html>
<html ng-app="app">

  <head>
    <script data-require="[email protected]" data-semver="1.4.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script>
      angular
        .module('app', [])
        .directive('parent', function() {
          return {
            scope: true,
            link: function(scope, element) {
              element.on('click', function() {
                scope.$broadcast('parent-event');
              });
            }
          };
        })
        .directive('child', function() {
          return {
            scope: true,
            link: function(scope) {
              scope.$on('parent-event', function() {
                console.log('child(' + scope.$id + ') caught parent event');
              });
            }
          };
        });
    </script>
  </head>

  <body>
    <div>
      <div parent> Parent {{ $id }}
          <div child>Child {{ $id }}</div>
      </div>

      <hr />

      <div parent> Parent {{ $id }}
          <div child>Child {{ $id }}</div>
      </div>
  </div>
  </body>
</html>

Plunker

Upvotes: 3

Przemek
Przemek

Reputation: 803

When you braodcast data you are doing that to all child scopes. Posible solution could be this:

$scope.$broadcast('customEvent', {
    target: ['dir1', 'dir2'],
    someProp: 'Sending you an Object!' // send whatever you want
});

and then in directive one

$scope.$on('customEvent', function (event, data) {
   if(data.target.indexOf('dir1') === -1 ) return;
});

Upvotes: 2

Related Questions