javascript - Add directives from directive in AngularJS -


i'm trying build directive takes care of adding more directives element declared on. example, want build directive takes care of adding datepicker, datepicker-language , ng-required="true".

if try add attributes , use $compile generate infinite loop, checking if have added needed attributes:

angular.module('app')   .directive('superdirective', function ($compile, $injector) {     return {       restrict: 'a',       replace: true,       link: function compile(scope, element, attrs) {         if (element.attr('datepicker')) { // check           return;         }         element.attr('datepicker', 'somevalue');         element.attr('datepicker-language', 'en');         // more         $compile(element)(scope);       }     };   }); 

of course, if don't $compile element, attributes set directive won't bootstrapped.

is approach correct or doing wrong? there better way achieve same behavior?

udpate: given fact $compile way achieve this, there way skip first compilation pass (the element may contain several children)? maybe setting terminal:true?

update 2: have tried putting directive select element and, expected, compilation runs twice, means there twice number of expected options.

in cases have multiple directives on single dom element , order in they’re applied matters, can use priority property order application. higher numbers run first. default priority 0 if don’t specify one.

edit: after discussion, here's complete working solution. key remove attribute: element.removeattr("common-things");, , element.removeattr("data-common-things"); (in case users specify data-common-things in html)

angular.module('app')   .directive('commonthings', function ($compile) {     return {       restrict: 'a',       replace: false,        terminal: true, //this setting important, see explanation below       priority: 1000, //this setting important, see explanation below       compile: function compile(element, attrs) {         element.attr('tooltip', '{{dt()}}');         element.attr('tooltip-placement', 'bottom');         element.removeattr("common-things"); //remove attribute avoid indefinite loop         element.removeattr("data-common-things"); //also remove same attribute data- prefix in case users specify data-common-things in html          return {           pre: function prelink(scope, ielement, iattrs, controller) {  },           post: function postlink(scope, ielement, iattrs, controller) {               $compile(ielement)(scope);           }         };       }     };   }); 

working plunker available at: http://plnkr.co/edit/q13but?p=preview

or:

angular.module('app')   .directive('commonthings', function ($compile) {     return {       restrict: 'a',       replace: false,       terminal: true,       priority: 1000,       link: function link(scope,element, attrs) {         element.attr('tooltip', '{{dt()}}');         element.attr('tooltip-placement', 'bottom');         element.removeattr("common-things"); //remove attribute avoid indefinite loop         element.removeattr("data-common-things"); //also remove same attribute data- prefix in case users specify data-common-things in html          $compile(element)(scope);       }     };   }); 

demo

explanation why have set terminal: true , priority: 1000 (a high number):

when dom ready, angular walks dom identify registered directives , compile directives 1 one based on priority if these directives on same element. set our custom directive's priority high number ensure compiled first , terminal: true, other directives skipped after directive compiled.

when our custom directive compiled, modify element adding directives , removing , use $compile service compile directives (including skipped).

if don't set terminal:true , priority: 1000, there chance directives compiled before our custom directive. , when our custom directive uses $compile compile element => compile again compiled directives. cause unpredictable behavior if directives compiled before our custom directive have transformed dom.

for more information priority , terminal, check out how understand `terminal` of directive?

an example of directive modifies template ng-repeat (priority = 1000), when ng-repeat compiled, ng-repeat make copies of template element before other directives applied.

thanks @izhaki's comment, here reference ngrepeat source code: https://github.com/angular/angular.js/blob/master/src/ng/directive/ngrepeat.js


Comments

Popular posts from this blog

java.util.scanner - How to read and add only numbers to array from a text file -

rewrite - Trouble with Wordpress multiple custom querystrings -