3

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

Nerdroid
  • 13,398
  • 5
  • 58
  • 69
Agat
  • 358
  • 2
  • 10
  • 1
    take a look at this link http://stackoverflow.com/questions/15266671/angular-ng-repeat-in-reverse – Punith Jain Dec 31 '14 at 13:13
  • Current example is broken because of transformation I chose to show the problem, .reverse(), is changing the array itself. Var a is tracking, .reverse() is changing it, $digest is going, .reverse() is going and on and on. Example need to be a little bit complex and accent on other detail, so I would create different question. Thanks everyone and sorry for not worked out question – Agat Dec 31 '14 at 15:16

4 Answers4

5

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

Community
  • 1
  • 1
Kareem Elshahawy
  • 1,421
  • 1
  • 12
  • 28
2

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>
rmuller
  • 1,837
  • 12
  • 12
  • See http://stackoverflow.com/questions/19693410/angularjs-error-10-digest-iterations-reached-aborting for more info – David Hughes Dec 31 '14 at 12:55
  • As I said, this is simplified example, and creation on new collection right inside ng-repeat is a critical part. In my real problem, for example, it was function that except collection and reducing it to new collection – Agat Dec 31 '14 at 12:56
  • Then you need to give us a better example to analyze. – Blazemonger Dec 31 '14 at 13:39
1

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.

Nicola Ferraro
  • 4,051
  • 5
  • 28
  • 60
0

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?

Community
  • 1
  • 1
selami
  • 1
  • 3