Javascript 自定义角度指令广播事件,但不广播嵌套子级?

Javascript 自定义角度指令广播事件,但不广播嵌套子级?,javascript,angularjs,angularjs-directive,angular-broadcast,Javascript,Angularjs,Angularjs Directive,Angular Broadcast,我已经在Angular中创建了一个accorbian指令,它可以嵌套,所以accorbian可以在其中包含子accorbian 我想在手风琴打开和关闭时广播一个事件,以便其他指令可以监听它(例如,打开手风琴面板内部的菜单时,它可能会显示自己) 问题是,如果外部元素中有嵌套的内部accorbian,我不希望事件被广播到内部accorbian的子元素,因为内部accorbian没有广播打开/关闭事件 以防这没有意义,换一种方式说,嵌套的accordian中的元素应该能够侦听它所在的accordian

我已经在Angular中创建了一个accorbian指令,它可以嵌套,所以accorbian可以在其中包含子accorbian

我想在手风琴打开和关闭时广播一个事件,以便其他指令可以监听它(例如,打开手风琴面板内部的菜单时,它可能会显示自己)

问题是,如果外部元素中有嵌套的内部accorbian,我不希望事件被广播到内部accorbian的子元素,因为内部accorbian没有广播打开/关闭事件

以防这没有意义,换一种方式说,嵌套的accordian中的元素应该能够侦听它所在的accordian所广播的打开/关闭事件,而不是DOM树上的一个

希望有一个简单的解决办法

更新:在此处添加了演示:

很明显,我还没有正确理解$broadcast和$on,因为演示活动目前根本不起作用,但应该清楚我在尝试做什么

编辑:显然,所有指向JSFIDLE的链接都必须附带代码,所以这里有一些

var app = angular.module('app', []);

app.controller('MainCtrl', function($scope) {
  $scope.mainMenuOpen = true;
})

.directive('myPanel', function() {
  return {
    restrict: 'EA',
    scope: {
      isOpen: '=?'
    },
    link: function($scope, $element, $attrs) {  
      $element.find('> BUTTON').bind('click', function() {

        $scope.isOpen = !$scope.isOpen;
        if ($scope.isOpen) {
          $scope.$broadcast('panelOpened');
        }
      });
    }
  };
})

.directive('reactToPanelOpenClose', function() {
  return {
    restrict: 'EA',
    scope: {},
    link: function($scope, $element, $attrs) {
      $scope.$on('panelOpened', function() {

        alert("clicked");

        $element.css({ 'background-color': 'red' });
      });
    }
  };
});

您可以添加一个数值
depth
或类似于您的广播,该数值定义了广播发送的层次深度。如果正在侦听的指令控制器的
深度
大于
1
,则可以执行。否则它可以忽略广播


如果不清楚,我还可以添加一个小示例,请告诉我。

到目前为止,最简单的方法是使用您在评论中提到的
require

解决这个问题的一种方法是注册子控制器(甚至它们的回调函数),然后父控制器可以调用每个子控制器,而不是广播

这里需要注意的是,您需要
require:“?^^parent”
-这意味着,将require设置为可选的,并且严格地说是祖先选择器;对于
“^”
Angular将返回self

.directive("accordion", function(){
  return {
    require: ["accordion", "?^^accordion"],
    controller: function(){
       var children = [];
       this.registerChild = function(childCtrl){
          children.push(childCtrl);
       }

       this.handleNotification = function(){
          // do something when notification arrives from parent
       }

       this.notify = function(){
          angular.forEach(children, function(child){
            child.handleNotification();
          })
       }
    },
    link: function(scope, element, attrs, ctrls){
      var me = ctrls[0], parent = ctrls[1];

      if (parent){
         parent.registerChild(me);
      } 
    }
  }
})

您试图在jQuery回调中使用角度上下文,所以这是行不通的。解决问题的最简单方法是以下代码段:

angular.$externalBroadcast = function (element, event, data) {
    var scope = element.scope();
    scope.$apply(function () {
        scope.$broadcast(event, data);
    });
};
并在面板指令的链接功能中应用此功能:

$scope.isOpen = !$scope.isOpen;                
if($scope.isOpen){
    angular.$externalBroadcast($element, 'panelOpened');
}

看看这篇修改过的文章。

这里有一些代码很有帮助,比如你的事件的名称,你从哪个范围广播/收听,等等……对不起,这里可能有太多的代码要发布,把它删减以制作JSFIDLE将是一个挑战。我可以随意调用这些事件,因为它们目前不存在,并假设我将从我创建的手风琴指令中播放它们。老实说,这不一定是关于我的手风琴指令,这更像是一个关于热的一般性问题,在链的下游广播一个事件,但当你到达一个相同类型的指令时停止。好吧,老实说,由于收件人不能取消
$broadcast
,所以你刚才描述的场景不容易建模。最简单的方法可能是以编程方式生成用于事件名称的字符串键,并以某种方式将该值传递给需要侦听的元素,以便每个手风琴都是唯一的。谢谢,这很有意义。我觉得$broadcast不能取消。我目前正在探索在子元素上使用require:^accorbian,并让它们注册回调或使用accorbian,而不是在阅读本文时使用$broadcast/$onIssue,这听起来比较复杂,但解决方案可能相对简单。我真的不知道用一个简化的演示来模拟它需要多长时间,而为了更好地理解您正在使用的东西,创建这个演示也不需要多长时间。。。垃圾输入,垃圾输出如果有帮助的话,我刚刚添加了一个JSFIDLE。谢谢,但是当您将对$broadcast的调用包装在$scope中时,为什么它不起作用。$apply(),为什么您需要创建一个外部函数?实际上,如果您这样做,它就起作用了$scope.$apply(函数(){$element.scope().$broadcast('panelOpened');})。。。但是如果您使用$scope.$broadcast(),则它必须是$element.scope()。$broadcast()谢谢,我想我可以修改此代码并使其工作。实际上,当手风琴打开时,需要做出反应的不是亚手风琴,而是另一个指令,需要它并注册回调,这样我就不必担心“自我”问题,我只需要把registerChild和notify函数放在accorbian上,把handleNotification放在另一个指令上,该指令正在accorbian上注册。