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、コメントでほのめかしたように使用することです。

これに対処する 1 つの方法は、子コントローラー (またはそのコールバック関数) を登録することです。これにより、親はブロードキャストの代わりに各子を呼び出すことができます。

ここで注意すべきことは、次のことを行う必要があるということです。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);
    });
};

そして、この関数を panel ディレクティブの link 関数内に適用します:

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

この変更されたFiddleを見てください。

于 2015-05-04T08:36:31.457 に答える
0

ブロードキャストが送信された階層の深さを定義する数値depthなどをブロードキャストに追加できます。ディレクティブコントローラーがリッスンしている場合、depthより1高い値を持っている場合、実行できます。それ以外の場合は、ブロードキャストを無視できます。

不明な場合は、小さな例を追加することもできます。お知らせください。

于 2015-05-03T23:31:20.503 に答える