0

I am fairly new to Angular. I have some code using ng-repeat.

This is the html:

<div ng-controller="myCtrl">
  <h2>Testing ng-repeat and sortable table</h2>
  <table>
    <tbody ui-sortable ng-model="list">
      <tr ng-repeat="item in list" style="cursor: move;">
        <td>{{log("ng-repeat on table with sorting:",$index); "index: " + $index + " array-item: " + item}}</td>
      </tr>
    </tbody>
  </table>

  <h2>Testing ng-repeat</h2>
  <div ng-repeat="item in list">
    {{log("ng-repeat on div",$index); "index: " + $index + " array-item: " + item}}
  </div>
</div>

This is the controller:

myapp.controller('myCtrl', function ($scope) {
  $scope.list     = ["a0","a1"];
  var count       = 0;

  $scope.log = function(title,index) {
    ++count;
    console.log(title, "count:", count, "index:", index);
  };
});

Plunkr http://plnkr.co/edit/uc7Bd3?p=preview

I was expecting to see 4 lines in the log (console), but there are 12 lines, as you see here:

ng-repeat on table with sorting: count: 1 index: 0
ng-repeat on table with sorting: count: 2 index: 1
ng-repeat on div count: 3 index: 0
ng-repeat on div count: 4 index: 1
ng-repeat on table with sorting: count: 5 index: 0
ng-repeat on table with sorting: count: 6 index: 1
ng-repeat on div count: 7 index: 0
ng-repeat on div count: 8 index: 1
ng-repeat on table with sorting: count: 9 index: 0
ng-repeat on table with sorting: count: 10 index: 1
ng-repeat on div count: 11 index: 0
ng-repeat on div count: 12 index: 1 

Why is it not only 4 lines (the number the two ng-repeats are looping through)?

EricC
  • 5,720
  • 13
  • 52
  • 71
  • possible duplicate of [Expression evaluated 2 times](http://stackoverflow.com/questions/15078231/expression-evaluated-2-times) – Stewie Jan 12 '14 at 22:37

2 Answers2

2

That's how angular works. It's called the digest loop and it executes each time something changes in the scope. ng-repeat is somewhat complex and the only way of actually understanding why this happens is by digging in the sources. Even though you don't change anything in your scope, ng-repeat changes a lot in it's scope and does a lot of $watching and $applying that trigger $digest loops. I'd start debugging on a dev version of angular (https://github.com/angular/angular.js/blob/34fee06ca7db16549764f53c0382f2b6e2482201/src/ng/directive/ngRepeat.js#L3).

Sergiu Paraschiv
  • 9,929
  • 5
  • 36
  • 47
2

It's expected behavior. ng-repeat calls log method twice (digest cycle). Angular watches to figure out what part of the DOM structure has been repainted.

If you want to avoid that, use $watch and drop all results if new value equals to old one.

Something like:

$scope.$watch('list', function(items) {
   for(var i = 0; i < items.length; i++) {
     var item = items[i];
    $scope.log("ng-repeat on table with sorting:",i);
   }
}, true);
Maxim Shoustin
  • 77,483
  • 27
  • 203
  • 225