4

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.

Ketan
  • 5,861
  • 3
  • 32
  • 39

2 Answers2

5

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.

jaime
  • 41,961
  • 10
  • 82
  • 52
  • The thing is $(".gallery") OR iElement in postlink does return the rendered UL with the LI and their bindings applied. The problem is in selection. Anything with a level down after .gallery does not work and that's what makes me think if Angular is using the full version of jquery or not. What I am trying to do is apply the jquery prettyPhoto plugin on the UL level once all the LIs have been bound and rendered. http://www.no-margin-for-errors.com/projects/prettyphoto-jquery-lightbox-clone/ – Ketan Dec 17 '12 at 22:18
0

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

ayortanli
  • 109
  • 11