隔离范围内的兄弟指令之间的通信

时间:2015-08-22 12:52:37

标签: angularjs

我试图让一个孩子的指令告诉它的兄弟姐妹一些信息已被更新。

我有这个标记:

  <rp-nav>
     <rp-nav-item cat="1"></rp-nav-item>
     <rp-nav-item cat="2"></rp-nav-item>
     <rp-nav-item cat="3"></rp-nav-item>

     <rp-flyout></rp-flyout>
  </rp-nav>

  <hr>

  <rp-nav>
    <rp-nav-item cat="one"></rp-nav-item>
    <rp-nav-item cat="two"></rp-nav-item>
    <rp-nav-item cat="three"></rp-nav-item>

    <rp-flyout></rp-flyout>
  </rp-nav>

我正在以这种方式使用事件:

angular.module('rpNavItem', [])
  .directive('rpNavItem', function() {
    return {
        restrict: 'E',
        controller: function($scope) {},
        controllerAs: 'ctrl',
        bindToController: true,
        // scope: true,
        template: function(el, attrs) {
          return  '<div>Item ' + attrs.cat + '</div>';
        },
        link: function(scope, el, attrs, ctrl) {
            el.on('click', function(){
                scope.$broadcast('selectedCat', attrs.cat);
            });
        }
    };
});

angular.module('rpFlyout', []).directive('rpFlyout', function() {
  return {
    restrict: 'E',
    controllerAs: 'ctrl',
    bindToController: true,
    // scope:true,
    controller: function($scope) {},
    template: '<p style="background-color: lightblue">{{category}}</p>',
    link: function(scope) {
      scope.$on('selectedCat', function(event, value){
        scope.category = value;
        scope.$digest();
        console.log(value);
      });
    }
  };
});

问题是每次我点击一个项目时,两个弹出窗口都会得到更新,我只想更新相应的一个。我怎样才能做到这一点? 这是在父隔离范围内限制的两个兄弟指令之间传递信息的正确方法吗?

Plunker

1 个答案:

答案 0 :(得分:1)

每个隔离范围都是相同$rootScope的子代,因此您无法使用事件来分隔指令。 $broadcast - ed事件用于全局(直到根)通信。

要直接与指令通信,您可以使用指令的require属性,因此rpNavItem可能需要rpNav并使用rpNav来共享状态。

javascript:

这个例子不需要

rpFlyout

angular.module('app', ['rpNav']);

angular.module('rpNav', [])
    .directive('rpNav', function() {
        return {
            scope: true,
            controller: ['$scope', function ($scope) {
              this.setSelectedCat = function (cat) {
                $scope.category = cat;
              }
            }]
        };
    });

angular.module('rpNav')
    .directive('rpNavItem', function() {
        return {
            restrict: 'E',
            scope: {
              cat: '@'
            },
            template: function (el, attrs) {
              return  '<div>Item ' + attrs.cat + '</div>';
            },
            require: '^rpNav',
            link: function (scope, el, attrs, rpNav) {
                el.on('click', function(){
                    scope.$apply(function () {
                      rpNav.setSelectedCat(scope.cat);
                    });
                });
            }
        };
    });

HTML可以变成:

<div rp-nav>
  <rp-nav-item cat="1"></rp-nav-item>
  <rp-nav-item cat="2"></rp-nav-item>
  <rp-nav-item cat="3"></rp-nav-item>

  <p style="background-color: lightblue">{{category}}</p>
</div>

<hr>

<div rp-nav>
  <rp-nav-item cat="one"></rp-nav-item>
  <rp-nav-item cat="two"></rp-nav-item>
  <rp-nav-item cat="three"></rp-nav-item>

  <p style="background-color: lightblue">{{category}}</p>
</div>

如果由于某种原因希望保留rpFlyout指令,则可以使其具有独立存储并传递属性中的当前类别(未经测试的代码):

<rp-flyout category="category"></rp-flyout>

指令:

[...]
.directive('rpFlyout', function() {
        return {
            scope: {
              'category': '='
            },
            template: '<p style="background-color: lightblue">{{category}}</p>'
        };
    });