7

我遇到了一个问题,我想绑定到 ng-repeat 循环内的函数的输出。我发现每个项目调用该函数两次,而不是我期望的一次。这是 ng-repeat 部分(注意末尾的 calcRowTotal() 调用):

<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>

calcRowTotal() 函数如下所示:

$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;
}

下面显示了正在迭代的项目之一的示例:

{
    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 }
    ]
}

我在控制台中看到以下内容(我正在循环的集合中当前有两个项目):

calcRowTotal - Index: 0 
calcRowTotal - Index: 1 
calcRowTotal - Index: 0 
calcRowTotal - Index: 1 

我当然可以创建一个“rowTotal”属性,但更愿意绑定到上面显示的函数提供的“实时”数据。希望重复是我所缺少的一些简单的东西,所以我感谢任何关于为什么我看到重复的反馈。附带说明一下,随着其中一个文本框中的数据发生变化,我也需要更新行总计,因此我可能需要一种不同的方法。不过,有兴趣首先了解这种特殊情况....绝对不希望重复,因为可能会有很多行。

这是一个例子:http: //jsfiddle.net/dwahlin/Y7XbY/2/

4

3 回答 3

13

这是因为您在这里绑定到一个函数表达式:

<td>{{calcRowTotal($index, row)}}</td>

它的作用是什么,它迫使对每个项目、每个摘要重新评估该功能。为了防止这种情况,您需要做的是预先计算该值并将其放入您的数组中。

一种方法是在您的阵列上设置一个手表:

$scope.$watch('timesheetRows', function(rows) {
   for(var i = 0; i < value.length; i++) {
     var row = rows[i];
     row.rowTotal = $scope.calcRowTotal(row, i);
   }
}, true);

然后你所要做的就是绑定到那个新值:

<td>{{row.rowTotal}}</td>
于 2013-02-20T18:31:08.653 回答
1

这完全是因为您按照@Ben Lesh 的建议绑定到函数表达式。不知何故,使用 $watch 也让我执行了两次相同的功能。我们使用的避免双重执行的解决方案是使用 ng-init 进行函数调用。只需创建一个以函数返回为值的初始化变量,并在您的表达式中使用它,如下所示:

<tr ng-repeat="row in timesheetRows" ng-init="rowTotalValue=calcRowTotal($index, row)">
<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>{{rowTotalValue}}</td>

这对我有用,因为我传递了行的单个属性。虽然没有尝试过 $index 。但我认为它应该工作。

于 2016-09-09T09:33:37.893 回答
0

我最近实际上遇到了类似的问题。

最终遍历每个子对象并将总数绑定到模型。应该不是问题,尤其是当您仅将总数用于显示目的时。

例如。

// Reset to Zero
$scope.rowTotal = 0;

jquery.each($scope.row, function(key, value) {
 $scope.totalRow += value.hours;
});

并遍历每一行。

于 2013-02-20T18:34:16.030 回答