How to add directives that takes care of adding more directives to the element it was created on? i.e. build a directive that takes care of adding date picker or other elements to the existing element.?
In cases where you have multiple directives on a single DOM element and where the order in which they’re applied matters, you can use the priority property to order their application. Higher numbers run first. The default priority is 0 if you don’t specify one. The key was to remove the attribute: element.removeAttr(“common-things”); and also element.removeAttr(“data-common-things”); (in case users specify data-common-things in the html).
See working solution with html below:
angular.module(‘plunker’)
.directive(‘commonThings’, function ($compile) {
return {
restrict: ‘A’,
replace: false,
terminal: true,
priority: 1000,
compile: function compile(element, attrs) {
element.attr(‘tooltip’, ‘{{dt()}}’);
element.attr(‘tooltip-placement’, ‘bottom’);
element.removeAttr(“common-things”);
return {
pre: function preLink(scope, iElement, iAttrs, controller) { },
post: function postLink(scope, iElement, iAttrs, controller) {
$compile(iElement)(scope);
} }; } }; );
<html ng-app=”plunker”>
<div ng-controller=”DatepickerDemoCtrl”>
<hr/>
<select ng-options=”s for s in selects” ng-model=”el” common-things>
<option value=””></option>
</select>
</div>
</html>
Explanation why we have to set terminal: true and priority: 1000 (a high number):
When the DOM is ready, angular walks the DOM to identify all registered directives and compile the directives one by one based on priority if these directives are on the same element. We set our custom directive’s priority to a high number to ensure that it will be compiled first and with terminal: true, the other directives will be skipped after this directive is compiled.
When our custom directive is compiled, it will modify the element by adding directives and removing itself and use $compile service to compile all the directives (including those that were skipped).
If we don’t set terminal:true and priority: 1000, there is a chance that some directives are compiled before our custom directive. And when our custom directive uses $compile to compile the element => compile again the already compiled directives. This will cause unpredictable behavior especially if the directives compiled before our custom directive have already transformed the DOM.