$timeout , in fact, is a legitimate way to solve this problem if you use inline template (unlike templateUrl ). This would not create race conditions.
What happens, Angular goes through the DOM and collects the directives and their functions before and after the link (by compiling the directives). Then, the communication functions for each directive for each node (i.e., the DOM element) are executed.
Usually the template for node (to which the directive applies) is already part of the DOM. So, if you have the following directive:
.directive("foo", function(){ return { template: '<span class="fooClass">foo</span>', link: function(scope, element){
he can find the element $(".fooClass") .
However, if the directive uses transclude: 'element' , for example ng-if ( ngIf.js ) and ng-repeat ( ngRepeat.js ), Angular rewrites the directive as a comment ( compile.js ), and therefore $(".item") ( in your example) does not exist until ng-repeat places it there. They do this in their scope.$watch ( ngIf.js ) function , depending on the value that they are viewing, and this may happen in the next digest loop. That way, even when your post link function works, the actual element you are looking for still does not exist.
.directive("foo", function(){ return { template: '<span ng-if="true" class="fooClass">foo</span>', link: function(scope, element){ // prints "" console.log(element.html()); } } }
But there will be - definitely - when $timeout starts.
source share