aju
aju

Reputation: 421

ng-repeat always rendering as last in directive template

I have a directive (<my-directive>) and child directives (<my-child-directive>) as below structure:

<my-directive>
        <my-child-directive caption="{{student}}" ng-repeat="student in students"></my-child-directive>
        <my-child-directive caption="static content1"></my-child-directive>  
</my-directive>

The first child directive repeated using ng-repeat and The last child directive is a static item.

Now I have two questions here:

Question1: In the final output, the last directive is rendering as first <li>. is there any way to render the <li>s in the same order of child directives?

Question2: I have used a hidden div in <my-directive>'s template to render the transclude for temporary purpose. Is there any way to avoid this unwanted div?

here is my java script code:

app=angular.module('myApp', [])
app.controller("MyController",function($scope){
    $scope.students=["Alex","George","Phillip"];
});


app.directive('myDirective',function(){
    return{
        restrict:'E',
        transclude:true,
        template:"<ul><li ng-repeat='item in items'>{{item.caption}}</li></ul> <div ng-transclude ng-hide='true'></div>",
        controller:function($scope){
            $scope.items=[];
            this.addItem=function(subScope){ 
                 $scope.items.push(subScope);   
            }
        },
        link:function(scope,element,attrs){ 
        }
    };
});

app.directive('myChildDirective',function () {
    return {
        restrict: 'E',
        require:"^myDirective",
        scope:{
            caption:"@"
        },

        link:function(scope,element,attrs,parentCtrl){
            parentCtrl.addItem(scope);
        }

    }
})

fiddle: http://jsfiddle.net/fyds082s/5/

Can anybody help on this?

Upvotes: 3

Views: 554

Answers (2)

New Dev
New Dev

Reputation: 49620

What order do you think the following would produce?

<my-directive>
  <my-child-directive caption="one" ng-if="true"></my-child-directive>
  <my-child-directive caption="two"></my-child-directive>
</my-directive>

If you answered two, one then hat's off to you.

The reason behind this somewhat unintuitive result is a "conditional rendering" directive like ng-if and ng-repeat. They both transclude their hosting element, but render it later - when $scope.$watch or $scope.$watchCollection fire an event, respectively - at which time the link function of myChildDirective is called.

The best approach is not to rely on the order of called link functions to determine the order of rendering.

Upvotes: 0

Moshe Shaham
Moshe Shaham

Reputation: 15994

The link function of the second directive is executed before the directives that come before him. When you check the ng-repeat state while the static directive is executed it shows that the index is 0. it hasn't finished compiling the ng-repeat yet.

My guess is that angular links sibling element from last to first, the same way it links from child elements first

Update:

My guess is wrong. so my new guess it has something to do with child scopes. For example, when adding ng-if to the second directive it is indeed executed second: http://jsfiddle.net/fyds082s/7/

<my-directive>
        <my-child-directive caption="{{student}}" ng-repeat="student in students"></my-child-directive>
        <my-child-directive caption="static content1" ng-if="true"></my-child-directive>  
</my-directive>

Upvotes: 0

Related Questions