Reputation: 358
The problem occurs when trying to ng-repeat over dynamically created collection: Angular is going in to loop with 10 $digest() iterations reached. Aborting!
error
I have simplified the problem to minimum with this example
<body ng-init='a = [1, 2, 3]'>
<div ng-repeat="item in a.reverse()">{{item}}</div>
</body>
and here is it working copy in Plunkr (View shows correct result, but in console you will see errors mentioned above. More complicated examples fail completely)
Considered [1, 2, 3] could be array of objects, if it may make any difference
So questions are why is it so, and is there an easy way to come over this?
Thanks
Upvotes: 3
Views: 859
Reputation: 1421
The problem is that you're calling the reverse function in ng-repeat and that $apply and $digest many times. If you're using AngularJS 1.3.x and your data will be created once and will not change at run-time, you can use bind-once property by typing the following in any of ng-(directives)
<body ng-init='a = [1, 2, 3].reverse()'>
<div ng-repeat="item in ::a">{{item}}</div>
</body>
prefixing a with :: tells AngularJS that this array or this variable won't be changed, so it will release the $watch function from it and won't consume $digest too many times.
For more information about bind once feature, check this one-time-binding
For the reversing technique itself if it's dynamically created and frequently changed, you can use one of the following approaches:
<body ng-init='a = [1, 2, 3]'>
<div ng-repeat="item in a.slice().reverse()">{{item}}</div>
</body>
or also you can wrap this into filter, you can use it as follows:
app.filter('reverse', function() {
return function(items) {
return items.slice().reverse();
};
});
and in the HTML type the following line of code:
<body ng-init='a = [1, 2, 3]'>
<div ng-repeat="item in a | reverse">{{item}}</div>
</body>
for ordering array of objects in general, you should use the following:
<body ng-init='a = [{id: 1}, {id: 2}, {id: 3}]'>
<div ng-repeat="item in a | orderBy:'id':true">{{item.id}}</div>
</body>
using true for reverse ordering and false for ascending ordering.
You can check also this question and answer for more information: angular ng-repeat in reverse
Upvotes: 5
Reputation: 1
using a function for ng-repeat is not a prefer way, you have to be carefully when using function for ng-repeat items. please check this post.
How to Loop through items returned by a function with ng-repeat?
Upvotes: 0
Reputation: 4189
This happens because angular uses a fixed-point model for rendering the objects in the page. When, after applying one iteration, all the "digest" of the objects do not change, the model is considered stable and it is rendered in the view. If the model is not stable after x=10 iterations, then an error is raised. In your case, the function reverse() generate always a new model object with a different digest.
For your particular problem, you can use ng-repeat with the orderBy clause (assuming that the model object is an array).
In general, when you have a main model and many derived sub-models, it is good practice to derive the sub-models using $watch expressions in a "reactive" fashion.
Upvotes: 1
Reputation: 1837
It is because of you calling the reverse() function in the ng-repeat.
Like this it works without errors
<body ng-init='a = [1, 2, 3].reverse()'>
<div ng-repeat="item in a">{{item}}</div>
</body>
Upvotes: 2