2013-10-13 6 views
20

Я пытаюсь достичь контроллера родительской «в поле» директива рекурсивно:Как получить доступ к контроллеру родительской директивы, требуя его рекурсивно?

<body ng-app="main"> 

<!-- no nesting: parent is the just body --> 
<box></box> 

<script type="text/javascript"> 
angular.module('main', []) 
.directive('box', function() { 
    return { 
     restrict: 'E', 
     controller: function() { }, 
     require: '?^box', // find optional PARENT "box" directive 
     link: function(scope, iElement, iAttrs, controller) { 
      // controller should be undefined, as there is no parent box 
      alert('Controller found: ' + (controller !== undefined)); 
     } 
    }; 
}); 
</script> 
</body> 

Я бы ожидать переменный контроллер, чтобы быть в функции связи undefined, но я получаю контроллер фактической директивы коробки ,

Так что мой вопрос ... как получить доступ к контроллеру РОДИТЕЛЕЙ в случае, как это:

<box> 
    <box></box> 
</box> 

http://jsfiddle.net/gjv9g/1/

ответ

18

OK, нашел ...

если вы хотите заполучить контроллер родительского элемента:

... 
link: function(scope, iElement, iAttrs, controller) { 
    // http://docs.angularjs.org/api/angular.element 
    // jQuery/jqLite Extras: 
    // 
    // controller(name) - retrieves the controller of the current element or its parent. 
    // By default retrieves controller associated with the ngController directive. 
    // If name is provided as camelCase directive name, then the controller for this 
    // directive will be retrieved (e.g. 'ngModel'). 
    var parentCtrl = iElement.parent().controller('box'); 
} 
... 

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

... 
controller: function($scope, $element) { 
    // store the element in controller, we'll need it later 
    this.$element = $element; 
}, 
// works in both pre and post link functions 
link: function() { 
    var parentElement = $element.parent(); 
    var parentCtrl = parentElement.controller('box'); 

    var hasDirectBoxParent = parentCtrl && parentCtrl.$element[0] === parentElement[0]; 

} 
... 

Пример 1:

<box id="a"> 
    <box id="b"></box> 
<box> 

Когда функция вызывается ссылка на «окне» а, parentCtrl в обоих случаях undefined. Когда функция ссылок вызывается в поле «b», parentCtrl является контроллером «box a» в обоих случаях.

Пример 2:

<box id="a"> 
    <div> 
     <box id="b"></box> 
    </div> 
<box> 

Когда функция вызывается ссылка на "окне" а, parentCtrl в обоих случаях undefined. Когда функция ссылок вызывается в поле «b», parentCtrl по-прежнему является контроллером «box a» в обоих случаях, но hasDirectBoxParent равен false, поэтому вы можете отличить родителя от дедушки и бабушки.

4

require впрыскивает контроллер от требуемых (родителя) директив в к текущая директива (из угловых документов: «требуется». Требовать другую директиву и вводить ее контроллер в качестве четвертого аргумента функции связывания «http://docs.angularjs.org/guide/directive)

Так что, возможно, вы уже получаете Что вы хотите? То есть родительский контроллер вводится детям через ваш параметр controller.

+0

как вы можете видеть, нет РОДИТЕЛЕЙ коробки в моем исходном примере, поэтому я ожидаю получить 'undefined' в качестве четвертого параметра для а не контроллер самого экземпляра – maX

+0

Но вы объявляете контроллер. Таким образом, родитель получает этот контроллер, а дети (если они существуют) наследуют его. Ваша цель узнать, является ли конкретная директива родителем или ребенком? Если это возможно, вы хотели бы посмотреть на $ parent scope? – KayakDave

+1

На самом деле я не хочу использовать область видимости в этом конкретном случае, так как области действия могут оказаться сложными, особенно если вам нужно использовать изолированную область. Кроме того, лучше всего использовать контроллеры и «требовать» для связи с директивой. Я считаю, что он работает как шарм, когда вам требуется родительская директива с другим именем, почему бы вам не сделать это рекурсивно. – maX

39

С помощью Angular 1.3 вы можете использовать два акцента ^^ для поиска директивы в родительских элементах «только».

Цитата из Angular Docs on require:

  • (no prefix) - Найдите нужный контроллер на текущий элемент. Выбросьте ошибку, если она не найдена.
  • ? - Попытайтесь найти требуемый контроллер или передать null в ссылку fn, если не найдено.
  • ^ - Найдите нужный контроллер , выполнив поиск элемента и его родителей. Выбросьте ошибку, если она не найдена.
  • ^^ - Найдите необходимый контроллер, выполнив поиск родителей элемента. Выбросьте ошибку, если она не найдена.
  • ?^ - Попытайтесь найти требуемый контроллер, выполнив поиск элемента и его родителей или передав null в ссылку fn, если не найден.
  • ?^^ - Попытайтесь найти требуемый контроллер, выполнив поиск родительских элементов или передайте null в ссылку fn, если он не найден.

В вашем случае замените require: '?^box', с require: '?^^box',

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