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>
http://jsfiddle.net/gjv9g/1/
In angular there is a scope variable called $parent (i.e. $scope. $parent). $parent is used to access parent scope from child controller in Angular JS.
Using $broadcast and $emit $broadcast always use to pass data from Parent Controller to child controller (Down direction) and $emit service use to pass data. From child controller to parent controller (Up direction).
Note: When you create a directive, it is restricted to attribute and elements only by default. In order to create directives that are triggered by class name, you need to use the restrict option. The restrict option is typically set to: 'A' - only matches attribute name. 'E' - only matches element name.
Using attrs you are able to access the attributes defined in your html tag like <fm-rating ng-model="$parent.restaurant.price" symbol="$" readonly="true"> So in this case you will have access to the symbol and readonly attributes.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With