I'm trying to reach the controller of a parent "box" directive recursively:
<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>
I'd expect controller variable to be undefined
in the link function, but I get the controller of the actual box directive.
So my question is ... how to gain access to the PARENT controller in case like this:
<box>
<box></box>
</box>
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.
来源:https://stackoverflow.com/questions/19340495/how-to-access-parent-directives-controller-by-requiring-it-recursively