0

I am new to this angular thing (and web-dev in general), but i have encountered a weird behavior concerning how the angular link function of a custom directive changes the DOM. More specifically the directive (using ng-repeat) creates multiple instances of a template: these instances are somehow accessible by document.getElementsByClassName() but not inside angular or jquery.

My index.html and group-widgets.html (containing template) are likewise:

<div class="groups_panel">
    <group-widgets class="col-md-12" style="margin-top:60px;"></group-widgets>
</div>

<div class="col-md-6 comment" ng-repeat="group in gWidget.groups">
    <div ...</div>
</div>

my app.js is like:

(function(){
    var app = angular.module('pm',[]);
    app.directive('groupWidgets',function(){
        return{
            restrict: 'E',
            templateUrl: 'group-widgets.html',
            controller:function($scope){
                this.groups = allGroups;
                console.log($scope);
                console.log("Wait till renders...");                
            },
            controllerAs: 'gWidget',
            link: function(scope, element, attributes, parentCtrl){
                console.log("LINKED!");
                console.log(document.getElementsByClassName("comment"));
                console.log(element.html());
                console.log($(".comment"));
                console.log("END");
            }
        };
    });
})();

The allGroups variable is an array whose elements ng-repeat instantiate. After running it with chrome dev tools I get: Screenshot (Check inside LINKED! and END).

It is obvious that during the linking function the DOM created by the ng-repeat (four instances as show in screenshot) is available with getElementsByClassName() but not within angular element object neither within the entire DOM using jQuery!

I have solved the problem as described in other questions (Calling a function when ng-repeat has finished.,AngularJS: Linking to elements in a directive that uses ng-repeat), but I cannot comprehend the order that directive link function works and why this is happening. Obviously I am making something wrong. Can you please help me clarify the issue?

Thanks in advance.

Community
  • 1
  • 1
  • Have you looked at http://stackoverflow.com/questions/12546945/difference-between-the-controller-link-and-compile-functions-when-definin ? – John Drouhard Apr 21 '15 at 22:31
  • What is `allGroups`? **EDIT** also can you try `document.getElementsByClassName("comment").length` as your second query and confirm whether it is 0 or 4? – Ed_ Apr 21 '15 at 22:44
  • Hi. @John Drouhard no, but helpful; also stating that link function - "It is executed after the template has been cloned" adds to my confusion. – Stefanos Stamatiadis Apr 22 '15 at 08:23
  • @Ed Hinchliffe the allGroups variable is an array whose elements ng-repeat instantiate;You're right: its 0 further adding to my confusion. But the solution starts to emerge and the culprit is HTMLCollection which is 'Live'. – Stefanos Stamatiadis Apr 22 '15 at 08:23

1 Answers1

2

What is happening here, which is what likely confused you, is that Chrome console evaluates a logged object at "view-time", not at "log-time".

Simple way to check is to do the following:

 console.log(document.getElementsByClassName("comment").length); // will be 0

So, the HTMLCollection that you get from document.getElementsByClassName is evaluated when you view the log, and thus contains the 4 divs.



(*) I'm not certain on the specifics of what exactly constitues "viewing", or what the actual trigger is, but it is not logging.

New Dev
  • 48,427
  • 12
  • 87
  • 129
  • Thanks for the prompt reply. I haven't been able to locate anything concerning the "view-time" VS "log-time", but from here [link](http://www.w3.org/TR/domcore/#concept-collection) I get that the HTMLcollection is empty when link function is executed (thus length==0) and during log-time the live collection gets updated. So I guess noob question from the start :) – Stefanos Stamatiadis Apr 22 '15 at 08:28