Angular ng-repeat - creating collection dynamically

The problem occurs when trying to ng-repeat over a dynamically created collection: Angular goes into a loop with an error 10 $digest() iterations reached. Aborting!

I have simplified the problem to a minimum with this example

<body ng-init='a = [1, 2, 3]'>
    <div ng-repeat="item in a.reverse()">{{item}}</div>
</body>

      

and here is a working copy in Plunkr (the view shows the correct output, but in the console you will see the errors mentioned above. in full)

It is considered [1, 2, 3] can be an array of objects, if it can have some value

So why is this and is there an easy way to overcome it?

thank

+3


source to share


4 answers


The problem is you are calling the inverse function in the ng-repeat and you are reusing $ apply and $ digest multiple times. If you are using AngularJS 1.3.x and your data will be created once and will not change at runtime, you can use the bind-once property by entering the following in any of the 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 will not be modified, so it will free the $ watch function from it and not digest $ digest too many times.

For more information about the binding function, follow these steps: one-time-binding

For the reverse technique itself, if it is dynamically created and changed frequently, you can use one of the following methods:

<body ng-init='a = [1, 2, 3]'>
  <div ng-repeat="item in a.slice().reverse()">{{item}}</div>
</body>

      

and also you can wrap this in a filter, you can use it like this:



app.filter('reverse', function() {
  return function(items) {
    return items.slice().reverse();
  };
});

      

and in the HTML text enter the following line of code:

<body ng-init='a = [1, 2, 3]'>
  <div ng-repeat="item in a | reverse">{{item}}</div>
</body>

      

to order an array of objects as a whole, 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 bottom ordering.

You can also check this question and answer for more information: angular ng-repeat backwards

+5


source


This is because you are calling the reverse () function in the ng-repeat.

How it works without errors



<body ng-init='a = [1, 2, 3].reverse()'>
   <div ng-repeat="item in a">{{item}}</div> 
</body>

      

+2


source


This is because angular uses a fixed point model to render objects on the page. When, after applying one iteration, the entire "digest" of objects does not change, the model is considered stable and rendered in the view. If the model is unstable after x = 10 iterations, then an error occurs. In your case, the reverse () function always generates a new model object with a different digest.

For your specific problem, you can use ng-repeat with an orderBy clause (assuming the model object is an array).

In general, when you have a base model and many derived submodels, it is good practice to retrieve the submodels using $ watch expressions in a "reactive" way.

+1


source


Using a function for ng-repeat is not the preferred way, you have to be careful when using a function for ng-repeat elements. please check this message.

How to loop through elements returned by a function using ng-repeat?

0


source







All Articles