Compiling Transcluded Content in AngularJS Directives
When you use the "transclude" option, in an AnglarJS directive, the transcluded content is automatically removed from its container, compiled, and made available through a linking function. This process keeps the transcluded content completely black-boxed. However, if we need to explicitly compile the transcluded content (so as to augment the pre-linked document object model), we can leverage Angular's ability to bind a single directive to multiple priorities on the same element.
When a directive is executed on an element, it's executed at a certain priority (defaults to zero). So, if you want to modify the DOM (Document Object Model) of your transcluded content before it's linked, you can't do this at the "transclusion priority." Instead, you have to do this before the transclusion priority; that is, you have to modify the pre-transcluded DOM at a higher priority.
That's a mouthful of poorly-articulated thoughts. Probably, this is just easier to see in code. In the following demo, I have a directive on a UL element. For the sake of the demo, the UL element is going to transclude the LI element and then simply re-append it. But, the key part of this exploration is the fact that the UL directive needs to add a CSS class to the LI template before the ngRepeat directive executes.
The UL won't have access to the LI content in either the compile() or the link() function of the transclude directive. As such, it will need to bind to another compile function, at a higher priority, so that it can add the CSS class prior to the transclusion:
As you can see, we're logging out the root element in the compile and link functions of the transclude directive. And, when we run this directive, we get the following console output:
Container at compile (html): (an empty string)
Container at link (html): (an empty string)
As you can see, when a directive uses "transclude", it can't access the transcluded content until it actually clones it. And, at that point, it's too late to alter the templates. However, since our directive was also bound to a compile function at a higher priority, it was able to add the CSS class, "item". And, as such, the ngRepeat included that class in each clone:
This is probably more of an edge case. And, you could always get around this by swapping the "transclude" property out with an explicit call to the $compile() function. But, I think it's good to know what content you have access to during the native transclusion lifecycle. And, what options you have.
Want to use code from this post? Check out the license.
Well man, this article came in handy for me, that's exactly what I've been looking for for hours. Thank you so much, makes my day !
Thanks a lot this was very educational and I used it in my project. Kinda gives me lisp macros vibes.
html is data :)
Thanks a ton.. very helpful article..
Glad you guys found this helpful :D
This was very helpful, thanks! Been banging my head against the wall trying to figure this out.
You are THE MAN. Thanks for this video!
This was the ticket to my problem. Thank you! Been reading your stuff for a while; First time commenting.