Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loop through the children of an element in a AngularJS directive

I have a problem - I've forgotten how to code! I have an angularJS directive that is on a parent wrapper tag (a DIV) and in my directive I wish to loop through the children (first Child DIVs). I have the following

<div data-check-attributes>
  <div data-ng-repeat="user in Users" data-id="{{ user.ID }}" data-ng-click="doSomething(user.ID)" data-new="{{ user.newUser }}" class="">
    <div> {{ user.userName }} </div>
    <div> {{ user.userAge }} </div>
  </div>
</div>

Now in my directive I wish to loop through the first child divs (there could be many of these, but I am seeing 10 users in my loaded view) and perform certain checks and modifications in my directive, using the data attributes, the $location object and potentially many more... however I can't remember how to loop through the first child divs, I seem to get errors with everything I tried... so far I have this, which doesn't work! In the example below I just want to write the data-id of the first child nodes to the console

.directive('checkAttributes', function ($location) {
        return{
            restrict: 'A',
            link: function (scope, element) {

            // will use $location later

                console.log(angular.element(element)[0]);  // this outputs the HTML
                console.log(angular.element(element)[0].children().length); // this errors, TypeError: object is not a function

                for (var i = 0; i < angular.element(element)[0].children.length; i++) {
                    console.log(angular.element(element)[0].children[i].getAttribute('data-id'));
                }

            }
        };
    });

I'm confused... please help!

like image 247
Mark Sandman Avatar asked Feb 26 '15 08:02

Mark Sandman


1 Answers

If you are trying to access children property of the HTMLElement then you should read it like property.

Another thing is that element is already an instance of angular.element so no need to wrap it again:

console.log(element[0]);  // DOM element
console.log(element[0].children.length);

However there is a set of convenience methods angular.element object provides. Those methods replicate some of the jQuery's methods, including $.fn.children method. In this case alternatively you can do

console.log(element);  // angular.element instance
console.log(element.children().length);

And finally, there is one more caveat: ngRepeat will render its elements after your custom directive, so you can't access children collection yet. Simplest fix is to wrap your code into $timeout service, which will execute your logic in the next digest cycle, guaranteed after ngRepeat is complete:

app.directive('checkAttributes', function($location, $timeout) {
    return {
        restrict: 'A',
        link: function(scope, element) {

            // will use $location later
            $timeout(function() {
                for (var i = 0; i < element[0].children.length; i++) {
                    console.log(element[0].children[i].getAttribute('data-id'));
                }
            });

        }
    };
});

Demo: http://plnkr.co/edit/oEOSY2e2E0mmLDQOHbff?p=preview

like image 126
dfsq Avatar answered Oct 19 '22 23:10

dfsq