Подтвердить что ты не робот

Как получить доступ к родительскому директивному контроллеру, потребовав его рекурсивно?

Я пытаюсь вернуться к контроллеру родительской директивы "box" рекурсивно:

<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.

Итак, мой вопрос: как получить доступ к контроллеру PARENT в таком случае:

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

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

4b9b3361

Ответ 1

ОК, нашел его...

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

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

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

...
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>

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

Пример 2:

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

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

Ответ 2

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

Цитата из Angular Документов на require:

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

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

Ответ 3

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

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