Recently I was putting together an AngularJS directive to use the Material Design specs for a stepper. Instead of just hardcoding in the values for each section of the form, which could have been an easy choice knowing that we had a deadline, or using jQuery to drop elements into the page, I was going to cleverly insert them while the outer directive was compiling. I’d heard a bit about the compilation process, but didn’t exactly know what it meant. For my purposes, I expected the sub-directives would be placed on the page once the space for them had been laid out and I knew that there are four hooks to choose from: the Compile method, the Controller method, the Pre-Link method, and the Post-Link method.
The Compile method only runs once for each directive type and seems to only be used for creating the Pre- and Post-Link methods, so that was out for adding elements to the DOM. The Controller method is used for code that is intended to be used at different points within the scope. The element is only in the DOM in its most basic form at this point, so I generally try to avoid any DOM manipulation here.
The Pre-Link function happens prior to transclusion and before the template is bound to the scope. More importantly, it runs before any Link functions on child elements. Google pretty aggressively tells you not to do any DOM manipulation here either, probably so that you don’t change the outer elements before the inner ones are set. Also, it still looks like this:
The Post-Link function happens after transclusions, after the template has been bound to the scope, and after all of the directives children have been linked as well. At this point it’s finally safe to manipulate the DOM and add something! But, upon putting a breakpoint in at this function, I saw that the DOM still looks like this:
There is still no space to put the sub-directives and, because Link has already been run on all children, I can’t just drop it in. I’ll need to compile it separately anyway.
At this point I’m a bit frantic because there isn’t another option on my list. I’m out of luck. By the time the html looks like it should, having run the ngRepeat and giving me space to insert the sub-directives, I no longer have any options. Apparently the ‘compilation process’ doesn’t quite mean what I thought it did.
So I beat an honorable retreat and ended up with jQuery. The $timeout and $compile services easily let me sidestep the stepper’s compilation process. Throwing it on the call queue instead of leaving it on the stack would guarantee that the ng-repeat had already been executed and there would be space to put the sub-sections. Of course, since then, Angular 1.5 came out with multiple-transclusion so now it’s apparently possible to hook into the process using that. Maybe for next time!