I am trying to manipulate DOM in an AngularJS Directive using a Jquery plugin.
I am not sure if AngularJs is using the full version of Jquery or not, although the full version script is on the head while AngularJs script is on the body so in theory AngularJS should use the full version. However, the log entry inside directive does not show anything is selected. While the exact same syntax inside Chrome console returns all the lis inside the ul.
Here's the Html
<ul id="myUl" class="gallery unstyled">
<li class="galleryitem" ng-repeat="i in images">
<a href="{{i.LargeImage.URL}}"><img ng-src="{{i.MediumImage.URL}}" /></a>
</li>
</ul>
Directive
.directive('gallery',function() {
return {
restrict : 'C',
link : function postLink(scope, iElement, iAttrs) {
console.log($(".gallery li"));
}
}
}
PS: I just realized that
console.log($(".gallery"));
does return the ul with li within them but not
console.log($(".gallery li"));
Which makes me think that the full version is not loaded.
jQuery is loaded, but when you call $('.gallery')
in the linking function the ng-repeater
expression has not been evaluated yet, so at that moment all those li
elements are not in the DOM. Just to experiment, you can add a delay before calling the selector
setTimeout(function(){
console.log($(".gallery li"));
}, 1000);
Then, you'll get all the li
elements because you are querying the DOM after ng-repeater
was evaluated. This is why running selecting the li
nodes from the console works.
Before continuing, when it's said that angular uses jQuery when the library is loaded means that angular.element
implements selectors and that references to elements inside directives have jQuery methods available. The recommendation is to manipulate the DOM in the context of the directive's element
iElement.find('li') // instead of $('.gallery li')
Now, you might be wondering, then how do I modify the DOM? Well, it depends of what exactly are you trying to achieve. Since you want to manipulate the DOM after all the li
have been rendered in the ngRepeater you might want to use a special directive checkLast
that checks when the last item in the repeater is rendered by checking if $last
is true
Here's a jsfiddle from someone in this google groups discussion.
Or you could $watch
for some scope property to change.
For those that look for some answer like me, try this one
.directive('gallery',function() {
return {
restrict : 'C',
link : function postLink(scope, iElement, iAttrs) {
iElement.ready(function(){
console.log($(".gallery li"));
});
}
}
}
by this way, you can assure that your iElement is ready for dom manipulation