3

Я создал аккордеонную директиву в Angular, которая может быть вложенной, поэтому аккордеон может иметь в себе дочерние аккордеоны.Пользовательская угловая директива вещания события, но не для вложенных детей?

Я хочу широковещать событие, когда аккордеон открывается и закрывается, так что другие директивы могут его прослушивать (например, меню внутри панели гармоник может обнаруживать себя, когда аккордеон внутри него открыт).

Дело в том, что если внутри внешнего встроен внутренний гармоник, я не хочу, чтобы событие транслировалось на дочерние элементы внутреннего гармоника, потому что внутренний гармоник не транслировал событие open/close.

На всякий случай это не имеет смысла, иначе говоря, элемент внутри вложенного аккордеона должен уметь прослушивать широковещательную передачу открытого/закрытого аккордеона, в которой он находится, а не дальше по дереву DOM ,

Надеюсь, это простое решение.

Update: добавил демо здесь: http://jsfiddle.net/jonhobbs/xr1kLqba/

я ясно не поняли $ вещания и $ на должным образом в качестве демо событий в настоящее время не работает вообще, но это должно быть ясно, что я пытаясь сделать!

Редактировать: По-видимому, все ссылки на 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' }); 
     }); 
    } 
    }; 
}); 
+0

здесь немного кода, например, названия ваших событий, масштаб которых вы передаете/слушаете, и т. Д .... – Claies

+0

Извините, здесь, вероятно, слишком много кода для публикации здесь и его сокращения, чтобы сделать jsfiddle вызовом. Я могу назвать события чем угодно, поскольку они в настоящее время не существуют, и предположим, что я буду транслировать их из созданной мной гармонической директивы. Честно говоря, это не обязательно должно быть о моей директиве-аккордеоне. Это скорее общий вопрос о том, как горячий транслировать событие по цепочке, но останавливайтесь, когда вы попадаете в директиву того же типа. – jonhobbs

+0

, честно говоря, поскольку «$ broadcast» не может быть отменена получателями, сценарий, который вы только что описали, нелегко смоделирован. Самый простой способ сделать это, вероятно, состоит в том, чтобы программно сгенерировать строковый ключ, который используется для вашего имени события, и каким-то образом передать это значение элементам, которые необходимо прослушать, чтобы каждый аккордеон был уникальным. – Claies

ответ

1

На сегодняшний день самым простым подходом является использование require, как вы упомянули в комментариях.

Один из способов решения этой проблемы - зарегистрировать дочерние контроллеры (или даже их функции обратного вызова), а затем родитель может позвонить каждому ребенку вместо трансляции.

Следует обратить внимание на то, что вам нужно будет require: "?^^parent" - это означает, что требуется дополнительный и строго предновый селектор; для "^" Угловая вернула бы себя.

.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); 
     } 
    } 
    } 
}) 
+0

Спасибо, я думаю, что смогу адаптировать этот код и заставить его работать. На самом деле это не субандайцы, которые должны реагировать, когда аккордеон открывается, это еще одна директива, которая должна требовать ее и зарегистрировать обратный вызов, поэтому мне не нужно беспокоиться о проблеме «я», мне просто нужно поставить registerChild и уведомлять функции на гармонике и handleNotification по другой директиве, которая регистрируется непосредственно с согласным. – jonhobbs

0

Вы можете добавить значение числа depth или аналогичных широковещательной передачи, которая определяет иерархическую глубину радиопередача была послана с. если прослушивание контроллера директив имеет значение depth1, оно может быть выполнено. Иначе это может просто игнорировать трансляцию.

Если неясно, я мог бы также добавить небольшой пример, просто дайте мне знать.

+0

Я просто добавил jsfiddle, если это поможет. – jonhobbs

1

Yo're пытается работать с угловым контекстом внутри обратного вызова 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.

+0

Спасибо, но почему это не работает, когда вы просто переносите вызов $ broadcast в $ scope. $ Apply(), зачем вам нужно создать внешнюю функцию? – jonhobbs

+0

На самом деле это работает, если вы это делаете ... $ scope. $ Apply (function() { $ element.scope(). $ Broadcast ('panelOpened'); }); ... но doens't, если вы используете $ scope. $ broadcast(), это должно быть $ element.scope(). $ broadcast() – jonhobbs

Смежные вопросы