2014-05-21 2 views
0

Я создал dropdownToggle директиву и имеет такие функции, как:Повторное использование функций директивы в другой директиве

toggle() 
isOpen() 
open() 
close() 
closeAll() 

Все они прекрасно работают только теперь у меня есть небольшая проблема. Мне нужно вызвать функцию closeAll() из другой директивы.

Причиной является то, что в моей основной области контента включен прослушиватель событий click, который должен закрыть все открытые панели раскрытия/меню в настоящее время.

Как это можно достичь? Я думал о том, чтобы переместить все эти функции в service, но я предпочел бы, если возможно, манипулировать DOM в директивах.

ответ

4

Это типичный случай, когда вам нужна одна директива для . Поведение другой директивы добавляет.
Согласно the docs свойство контроллер директивы определения объекта, что вам нужно:

контроллер
функции конструктора контроллера. Контроллер создается до фазы предварительной привязки и делится с другими директивами (см. Атрибут require). Это позволяет директивам общаться друг с другом и дополнять поведение друг друга. Контроллер инъекционный (и поддерживает кронштейн обозначения) со следующими местными жителями:

  • $ рамки - текущая область, связанная с элементом
  • $ элемента - Текущий элемент
  • $ ATTRS - Текущие атрибуты объекта для элемента
  • $ transclude - функция перекрестной ссылки, предварительно привязанная к правильной области затенения. Область действия может быть переопределена необязательным первым аргументом. функция ([scope], cloneLinkingFn).

Для того, чтобы получить доступ к контроллеру первой директивы вам нужно require его от второго:

.directive('directive1', function() { 
    return { 
     ... 
     controller: function ($scope, $element, $attrs) { 
      this.doSomething = function() { 
       alert('Directive1: Done something !'); 
      }; 
     }, 
     ... 
    }; 
}); 

.directive('directive2', function() { 
    return { 
     ... 
     require: 'directive1', 
     link: function postLink(scope, elem, attrs, dir1Ctrl) { 
      scope.doSomething = dir1Ctrl.doSomething; 
     } 
    }; 
}); 

См, также, это short demo.

0

Вы можете указать свои функции в контроллере директивы, а затем потребовать его от другой директивы. Другим способом будет emit или broadcast пользовательским событием, на котором вы будете слушать в контроллере назначения.

Если вы этого не знаете, ознакомьтесь с учебниками по адресу egghead.io, они были для меня полезными. В частности, это один обращается именно ваш вопрос:

egghead.io - Directive communication

0

Услуга является вариант, он делает не должны делать манипуляции DOM. Экземпляры директивы (или любой другой директивы, заинтересованной в участии в этом поведении) могли бы зарегистрироваться в службе для уведомления. Сама услуга будет выполнять только часть уведомления.

Если это только уведомления, это может быть сделано с событием на $rootScope, то есть с использованием $rootScope.$on() и $rootScope.$emit() для этой цели.

В любом случае, не забудьте отменить слушатель $destroy: $scope.$on("$destroy", function() { /*unregister listener here*/ }) (подсказки: scope.$on() возвращает функцию отмены регистрации).

+0

Вам не нужно выделять/транслировать из rootScope, так как директивы также имеют доступ к области. – link

+0

Директивы могут - в общем случае - размещаться в любом месте иерархии. Их области могут быть братьями и сестрами, и в этом случае '$ emit'-ing /' $ broadcast'-ing не будет передавать событие. 'emit'-ing на' $ rootScope' достигает 2-х вещей: все они получают сообщение, так как существует только один '$ rootScope', и существует минимальное количество областей видимости, что позволяет свести к минимуму штрафы за производительность (' $ emit'- ing/'$ broadcast'-ing в любой другой внутренней области затронет либо его родителей, либо своих детей, а' $ rootScope' не имеет родителей, чтобы пересылать событие '$ emit'-ed, поэтому он остается там. –

+0

Вы правы, я не думал о случае братьев и сестер. – link

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