7

ng-repeat ループ内の関数の出力にバインドしたいという問題が発生しています。関数が、期待どおりに 1 回ではなく、アイテムごとに 2 回呼び出されていることがわかりました。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;
}

反復される項目の 1 つの例を次に示します。

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

コンソールに次のように表示されます (現在、ループしているコレクションに 2 つのアイテムがあります)。

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

確かに「rowTotal」プロパティを作成できますが、上記の関数によって提供される「ライブ」データにバインドすることをお勧めします。うまくいけば、重複は私が見逃している単純なものなので、なぜ重複が見られるのかについてのフィードバックをいただければ幸いです。補足として、テキスト ボックスの 1 つのデータが変更されると、行の合計も更新する必要があるため、別のアプローチが必要になる場合があります。ただし、この特定の状況を最初に理解することに興味があります....潜在的に多くの行が存在する可能性があるため、間違いなく重複は望ましくありません。

例を次に示します: http://jsfiddle.net/dwahlin/Y7XbY/2/

4

3 に答える 3

13

ここで関数式にバインドしているためです。

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

それは、すべてのアイテム、すべてのダイジェストでその関数を強制的に再評価することを意味します。それを防ぐためにやりたいことは、その値を事前に計算し、それを配列に入れることです。

これを行う 1 つの方法は、アレイにウォッチを設定することです。

$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 を使用すると、同じ関数を 2 回実行することにもなりました。私たちが使用した二重実行を避けるための解決策は、関数呼び出しに ng-init を使用することです。関数 return を値として使用して init 変数を作成し、それを以下のように ur 式で使用するだけです。

<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 に答える