AngularJs - Error: 10 $digest() iterations reached. Aborting

user2859298 picture user2859298 · Oct 30, 2013 · Viewed 16.8k times · Source

I am trying to create a Metro Tile type grid with Angular, to achieve this i want each of the tiles to be a different colour. So my plan of action was to create a function that would randomly pick a colour inside a loop (using ng-repeat). Here is what i have so far....

<div class={{RandomColourClass()}} ng-repeat="stockRecord in GridStockRecords | filter:searchText">
  <div  >
    <h6>{{stockRecord.ProductGroupName}}</h6>
  </div>
</div>

So as you can see i am setting the class name with a function called RandomColourClass, Here is the JS bits

$scope.TileColours = [{colour:'thumbnail tile tile-blue'},{colour:'thumbnail tile tile-green'},{colour:'thumbnail tile tile-red'}];

$scope.RandomColourClass = function(){
  var randomColour = $scope.TileColours[Math.floor(Math.random() * $scope.TileColours.length)];
  return randomColour.colour.toString();
};

This all works fine and the tiles are of different colours but i keep getting the following error

Error: 10 $digest() iterations reached. Aborting!".

I've had a look at other posts around the issue but i can't figure out what i need to change to get it working!? Any help or direction would be greatly appreciated :)

Answer

John Ledbetter picture John Ledbetter · Oct 30, 2013

Angular performs a digest function to update the DOM when your data changes.

During the digest, it recomputes all the values you have bound in the DOM, in this case {{RandomColorClass()}}. If any of them change, it again performs a digest cycle (since some variables may depend on the value of of the changed variable, for example).

It does this repeatedly until two digests in a row result in the same values -- i.e, nothing has changed.

What's happening is that when a digest occurs, your RandomColorClass() function is being called and returns a different value. This triggers an additional digest, where RandomColorClass() again returns a different value, which triggers another digest...

Can you see where this is going? You shouldn't be generating random values in this manner -- instead, generate them in your scope and persist them.

One approach might be, in your scope:

function randomColourClass() { /* ... */ };

$scope.GridStockRecords.forEach(function(record) {
  record.colorClass = randomColourClass(); 
});

and HTML:

    <div ng-repeat="stockRecord in GridStockRecords | filter:searchText"
         ng-class="stockRecord.colorClass">
      <div>
        <h6>{{stockRecord.ProductGroupName}}</h6>
      </div>
    </div>