Search code examples
javascripthtmlangularjsangularjs-scope

Increment value of scope counter by 1 gives 10 $digest() iterations reached. Aborting error message


I am trying to work with angularjs and given is the JSFiddle for what I am trying to do

<div id="page-main-body">
  <div id="container" ng-repeat="hero in heroModel">
    <div id="page-header" ng-if="heroCounter === 1">
      I am header
    </div>

    <div id="page-body">
      <p>Name: {{ hero.Name }}</p>
      <p>Super hero identity: {{ hero.SuperHeroName }}</p>
    </div>

    <div id="page-footer" ng-if="heroCounter === 2">
      I am footer
    </div>
    {{ incrementHeroCounter() }} {{ resetHeroCounter() }}
  </div>
</div>

My issue is if my model contains 4 elements it works fine, but if i remove one element from the model I don't see the footer div and I get an error message in the console which says

10 $digest() iterations reached. Aborting! Watchers fired in the last 5 iterations:

So I think this is because I am updating the $scope variable and based on the variable value i am drawing my header and footer.

Everything works fine if my data model contains 4 or 6 elements but if i change the element count from an even count (2,4) to an odd count (1,3) I get the $digest error

I also read the angular documentation for this error but it seems like my model too remains the same and nothing changes, only variable which changes is the $scope variable of counter here and I know that may cause a change in the digest cycle but how do i cache it or use a different technique to achieve what i am trying to do here

I tried couple of previous stack links but was unable to get a good direction from it, I am not sure if for a simple thing like this i should use service or a $rootScope maybe there's a better way of doing this.

Given below is how my code looks like you may also look at the fiddle and let me know what i am doing wrong here

var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
  $scope.heroCounter = 1;

  $scope.incrementHeroCounter = function() {
    $scope.heroCounter++;
  };

  $scope.resetHeroCounter = function() {
    if ($scope.heroCounter === 3) {
      $scope.heroCounter = 1;
    }
  };

  $scope.heroModel = [
    {
      SuperHeroName: "Superman",
      Name: "Clark kent"
    },
    {
      SuperHeroName: "Batman",
      Name: "Bruce Wyane"
    },
    {
      SuperHeroName: "Iron man",
      Name: "Tony Stark"
    },
    {
      SuperHeroName: "Shazam",
      Name: "Billy Batson"
    }
  ];
});

Solution

  • i want to print the header and then 2 div elements with data and then the footer, the third and fourth item should be printed with their own header and footer.

    Use the $index special property:

    <div id="page-main-body">
      <div id="container" ng-repeat="hero in heroModel">
        <div id="page-header" ng-hide="$index === 1">
          I am header
        </div>
    
        <div id="page-body">
          <p>Name: {{ hero.Name }}</p>
          <p>Super hero identity: {{ hero.SuperHeroName }}</p>
        </div>
    
        <div id="page-footer" ng-hide="$index === 0">
          I am footer
        </div>
        ̶{̶{̶ ̶i̶n̶c̶r̶e̶m̶e̶n̶t̶H̶e̶r̶o̶C̶o̶u̶n̶t̶e̶r̶(̶)̶ ̶}̶}̶ ̶{̶{̶ ̶r̶e̶s̶e̶t̶H̶e̶r̶o̶C̶o̶u̶n̶t̶e̶r̶(̶)̶ ̶}̶}̶
      </div>
    </div>
    

    The $index special property is exposed on the local scope of each ng-repeat template instance. It is a number iterator offset of the repeated element (0..length-1).

    For more information, see