Sometimes you want your AngularJS directive to execute after the affected
element has been added to the DOM and had its styles computed.
This can often be solved by putting your DOM-specific logic inside a $timeout
and executing it on the next tick. But the $timeout trick does not
guarantee that the element will be ready to manipulate.
I was working with a directive that needed to access the element’s computed
width property, using the $window.getComputedStyle method. If the directive
fires before the styles are computed, it simply returns “auto” for the width
value.
I needed to get some numeric value back (e.g. “421px”); “auto” is not a useful response:
In this scenario, wrapping this up in a $timeout was insufficient to solve the problem.
getComputedStyle was still returning “auto”, even when I tried passing fudge-factor
milliseconds to $timeout. Up to 200ms was still not guaranteed to return the pixel value I
needed.
The solution was to use the magic of recursion:
That’s not bad, but we can do better:
Backstop the recursion with a limited number of tries.
Make the timeout milliseconds and number of tries configurable.
Taking those two requirements into account, the directive’s link function winds up
looking something like this:
Et voilá—this directive will now delay running until the element’s computed
styles are available, or die trying.