How to access parent directive's controller by requiring it recursively?

时光总嘲笑我的痴心妄想 提交于 2019-11-28 18:21:21

Since Angular 1.3 you can use two accents ^^ to search for a directive in parent elements "only".

Quote from the Angular Docs on require:

  • (no prefix) - Locate the required controller on the current element. Throw an error if not found.
  • ? - Attempt to locate the required controller or pass null to the link fn if not found.
  • ^ - Locate the required controller by searching the element and its parents. Throw an error if not found.
  • ^^ - Locate the required controller by searching the element's parents. Throw an error if not found.
  • ?^ - Attempt to locate the required controller by searching the element and its parents or pass null to the link fn if not found.
  • ?^^ - Attempt to locate the required controller by searching the element's parents, or pass null to the link fn if not found.

In your case, replace require: '?^box', with require: '?^^box',

OK, found it...

if you want to get hold of the controller of a parent element:

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

This returns either controller of parent directive or, one level higher, the controller of parent's parent directive, If you need to make sure you get a controller of a DIRECT parent, I found this (maybe there is a better solution, I don't know):

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

}
...

Example 1:

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

When the link function is invoked on "box a", parentCtrl is undefined in both cases. When the link function is invoked on "box b", parentCtrl is the controller of "box a" in both cases.

Example 2:

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

When the link function is invoked on "box a", parentCtrl is undefined in both cases. When the link function is invoked on "box b", parentCtrl is still the controller of "box a" in both cases, but hasDirectBoxParent is false, so you can distinguish parent from a grandparent.

require injects the controller from the required (parent) directive in to the current directive (from the angular docs: "require - Require another directive and inject its controller as the fourth argument to the linking function" http://docs.angularjs.org/guide/directive)

So maybe you're already getting what you want? That is, the parent controller injected in to the children via your controller parameter.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!