Say I have two directives, my-awesome-table
and my-awesome-table-cell
. I never want my-awesome-table-cell
to be used outside of the my-awesome-table
directive. Is there a way to enforce this? So that an error is thrown when it is used outside the my-awesome-table
directive?
You can also do this by getting the outer directive to put a "controller directive" on the DOM and then getting the inner directive to "require" this "controller directive".
See this Plunk:http://plnkr.co/edit/QPNPu4.
app.directive('myAwesomeTable', function() {
return {
controller: function($scope) {},
link: function(scope, element) {
...
}
};
});
app.directive('myAwesomeTableCell', function() {
return {
require: '^myAwesomeTable',
link: function(scope, element, attributes, controller) {
...
}
};
});
You can also make the requirement optional using ?^ and then check inside your linking function for the controller parameter being defined if you want fine grained control over this.
This shouldn't be an issue, presuming you'll have control over your own code... However, in the circumstance it becomes an issue, you can check in your linking function to see if your directive is contained in proper parent directive:
app.directive('testChild', function() {
return {
restrict: 'E',
template: '<div>child</div>',
link: function(scope, elem, attr){
if(elem.parents('test').length === 0) {
throw new Error('Must be inside test directive');
}
}
};
});
app.directive('test', function(){
return {
restrict: 'E',
transclude: true,
template: '<div>' +
'<h3>parent</h3>' +
'<div ng-transclude></div>' +
'</div>'
};
});
Test Markup:
<test>
<test-child></test-child>
<test-child></test-child>
</test>
<!-- this will throw an error in JS -->
<test-child></test-child>
NOTES
The elem
argument in the link function is a JQuery LITE object unless you're also referencing JQuery, then it's a full JQuery object. JQuery Lite does not have a .parents()
function. You can still check the parents, but I'd recommend using JQuery here if possible.
Another thing to know is the directive in error will still render, unless you use elem.remove()
to get rid if it in the link function.
Also, if you use replace:true
on your parent directive, you're going to need to put something in it's template to identify it, like a class or attribute you can query for with the parent()
call.