Normal use cases in angular
If you have a parent directive and a child directive you create methods in the controller of the parent directive and re
Actually there is another way that is less verbose and is used by the angular ngModel itself:
var parentForm = $element.inheritedData('$formController') || ....
Basically they use the fact that the controllers are stored into the data property of the directive dom element.
Still a bit wired, but less verbose and easier to understand.
I don't see a reason why you cannot pass the required controllers into the injection locals for the directive controller.
The question is in what order directives are compiled and linked. Suppose we have a html structure like this:
<div top>
<div middle>
<div bottom></div>
</div>
</div>
and the coresponding (simplyfied) directives with a lot of debug output:
.directive('top', function() {
return {
controller : function($scope, $element, $attrs) {
this.topMethod = function() {
console.log('top method');
}
},
compile : function($element, $attrs) {
console.log('top compile');
return {
pre : function($scope, $element, $attrs) {
console.log('top pre');
},
post : function($scope, $element, $attrs) {
console.log('top post');
}
};
}
}
})
.directive('middle', function() {
return {
require : "^top",
controller : function($scope, $element, $attrs) {
this.middleMethod = function() {
console.log('middle method');
$scope.topController.topMethod();
}
},
compile : function($element, $attrs) {
console.log('middle compile');
return {
pre : function($scope, $element, $attrs, topController) {
console.log('middle pre');
$scope.topController = topController;
},
post : function($scope, $element, $attrs, topController) {
console.log('middle post');
}
};
},
}
})
.directive( 'bottom', function() {
return {
require : "^middle",
compile : function($element, $attrs) {
console.log('bottom compile');
return {
pre : function($scope, $element, $attrs, middleController) {
console.log('bottom pre');
middleController.middleMethod();
},
post : function($scope, $element, $attrs, middleController) {
console.log('bottom post');
}
};
}
}
})
we got the following output:
top compile
middle compile
bottom compile
top pre
middle pre
bottom pre
middle method
top method
bottom post
middle post
top post
As we can see first the compile function is called. Then the pre linking function is called and after that the post linking function is called. compile and pre are going from top to bottom and post goes from bottom to top. So we have to set the controller in the pre linking function.
Taken from romario333's comment: The cleanest solution is to simply use
var topController = $element.controller('top') // pass directive name or controller name
From the docs:
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').
$element can be injected into your directive controller.