3

我在 Angular 中创建了一个可以嵌套的手风琴指令,因此手风琴可以在其中包含子手风琴。

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

问题是,如果在外部手风琴内部有一个嵌套的内部手风琴,我不希望将事件广播到内部手风琴的子元素,因为内部手风琴没有广播打开/关闭事件。

以防万一这没有意义,换句话说,嵌套手风琴内的元素应该能够收听它所在的手风琴广播的打开/关闭事件,而不是 DOM 树上更远的那个。

希望有一个简单的解决方案。

更新:在此处添加演示:http: //jsfiddle.net/jonhobbs/xr1kLqba/

我显然没有正确理解 $broadcast 和 $on ,因为演示活动目前根本不起作用,但应该清楚我想要做什么!

编辑:显然所有到 jsfiddle 的链接都必须附有代码,所以这里有一些。

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' });
      });
    }
  };
});
4

3 回答 3

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);
      } 
    }
  }
})
于 2015-05-04T06:43:26.957 回答
1

你正在尝试在 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');
}

看看这个修改后的Fiddle

于 2015-05-04T08:36:31.457 回答
0

您可以在广播中添加一个数值depth或类似的值,它定义了发送广播的层次深度。如果指令控制器监听,有更高depth1,它可以执行。否则它可以忽略广播。

如果不清楚,我也可以添加一个小例子,让我知道。

于 2015-05-03T23:31:20.503 回答