Hm, next stumbling block: the static 'name' value from above. 
I'd like to get that value from an expression, evaluated against the scope 
of the element.

Which forces me to put the attr.$set call into the link function. That, 
again, will cause ngModel to not pick up the binding.
Again, the rendered dom will have eg.
<input foo ng-model="formData.email">
correctly, but will not bind to formData.email.

Here's a jsbin: http://jsbin.com/OyaCigE/5/edit?html,js,output

Further ideas?

On Thursday, January 9, 2014 12:49:13 PM UTC+1, Carsten Kraus wrote:
>
> Cool, thanks both of you! Both approaches actually work as I intended.
>
> @Daniel: wow, AWESOME reply! Thanks for bringing me to the next directive 
> grokking level : )
>
> Fwiw, I'll rename the resume func to something more verbose like 
> resumeCompilation as it not only applies to the ngModel directive.
>
> Cheers, 
> Carsten
>
> On Thursday, January 9, 2014 1:55:55 AM UTC+1, Daniel Tabuenca wrote:
>>
>> This is a common requirement, but it’s not immediately clear how to do it 
>> in a straight-forward fashion. I’ve talked with Miško from the angular team 
>> and he confirmed that the following is the propper way to dynamically add 
>> directives:
>>
>> app.directive('foo', function($compile, $parse) {
>>   return {
>>     restrict: 'A',
>>     priority: 9999,
>>     terminal: true, //Pause Compilation to give us the opportunity to add 
>> our directives
>>     compile: function(el, attr) {
>>       attr.$set('ngModel', 'name')
>>       var ngModelLink = $compile(el, null, 9999); //Resume compilation at 
>> priority 9999 so that our directive doesn't get re-compiled
>>       return function(scope) {
>>         ngModelLink(scope); //Return the link function from the new 
>> compilation
>>       }
>>     }
>>   }
>> });
>>
>> The problem is that angular determines the list of directives to compile 
>> *BEFORE* your directive is called. By the time you are executing your 
>> compile function, it is too late and angular won’t compile any additional 
>> directives you add to the current element (although it will compile 
>> anything you add to children). 
>>
>> We cannot simply add the directive to element and call $compile() on it 
>> either because then our directive will be compiled again, causing an 
>> infinite loop.
>>
>> What we have to do is stop compilation at our directive (by giving it a a 
>> high priority and adding terminal: true. We can then add the attributes 
>> to the element and call $compile() but pass it which priority to compile 
>> from. If we pass the same priority as our directive it means our directive 
>> and any higher-priority directives will not be compiled again (only 
>> directives lower than the priority passed in will get compiled). This 
>> allows us to essentially resume compilation allowing angular to scan for 
>> any new directives and compile them.
>>
>> There are a few other ways you can do this, but this one is the cleanest. 
>> I’ve seen other people inject the directives themselves (e.g. 
>> ngModelDirective) and then manually call the compile and link functions on 
>> them, but this gets tricky when directives have additional require:sections 
>> and is just not as clean.
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to angular+unsubscr...@googlegroups.com.
To post to this group, send email to angular@googlegroups.com.
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to