Function Called Multiple Times in AngularJS Repeat Section
angularjs, javascript
Solution
It's because you're binding to a function expression here:
<td>{{calcRowTotal($index, row)}}</td>
What that does it force that function to be reevaluated on every item, on every digest. What you'll want to do to prevent that is pre-calculate that value and put it in your array to begin with.
One way to do that is to set up a watch on your array:
$scope.$watch('timesheetRows', function(rows) {
for(var i = 0; i < value.length; i++) {
var row = rows[i];
row.rowTotal = $scope.calcRowTotal(row, i);
}
}, true);
Then all you have to do is bind to that new value:
<td>{{row.rowTotal}}</td>
Problem
I'm running into an issue where I want to bind to the output of a function inside of an ng-repeat loop. I'm finding that the function is being called twice per item rather than once as I'd expect. Here's the ng-repeat section (notice the calcRowTotal() call at the end): ``` <tr ng-repeat="row in timesheetRows"> <td> <select ng-model="row.categoryID"> <option ng-repeat="category in categories" value="{{category.id}}"> {{category.title}} </option> </select> </td> <td ng-repeat="day in row.dayValues"> <input type="text" ng-model="day.hours" /> </td> <td>{{calcRowTotal($index, row)}}</td> </tr> ``` The calcRowTotal() function is shown next: ``` $scope.calcRowTotal = function (index, row) { console.log('calcRowTotal - Index: ' + index); var total = 0; for (var i = 0; i < row.dayValues.length; i++) { var num = parseFloat(row.dayValues[i].hours); if (isNaN(num)) { num = 0; //this.dayValues[i].hours = 0; } total += num; } //updateDayTotals(); return total; } ``` An example of one of the items being iterated through is shown next: ``` { categoryID: 2, dayValues: [ { day: $scope.days[0], hours: 5 }, { day: $scope.days[1], hours: 0 }, { day: $scope.days[2], hours: 3 }, { day: $scope.days[3], hours: 0 }, { day: $scope.days[4], hours: 2 }, { day: $scope.days[5], hours: 5 }, { day: $scope.days[6], hours: 8 } ] } ``` I'm seeing the following in the console (two items are currently in the collection I'm looping through): ``` calcRowTotal - Index: 0 calcRowTotal - Index: 1 calcRowTotal - Index: 0 calcRowTotal - Index: 1 ``` I could certainly make a "rowTotal" property but would prefer to bind to "live" data provided by the function shown above. Hopefully the duplication is something simple I'm missing so I appreciate any feedback on why I'm seeing the duplication. As a side note, as data in one of the textboxes changes I need to update the row totals as well so it may be I need a different approach. Interested in understanding this particular situation first though....definitely don't want the duplication because there could be a lot of rows potentially. Here's an example: http://jsfiddle.net/dwahlin/Y7XbY/2/