2013-02-20 22 views
7

ng-repeatループ内の関数の出力にバインドする問題が発生しています。私は期待していたように、関数が1回ではなく2回呼び出されていることがわかりました。AngularJSリピートセクションで複数回呼び出される関数

<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()関数は次示されている:ここでNGリピート部(端で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 } 
    ] 
} 

私は(2つの項目が、私はをループしていますコレクションに現在ある)コンソールで、次の見ている:

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

私は確かに "rowTotal"プロパティを作ることができますが、上記の関数で提供される "ライブ"データにバインドする方が好きです。うまくいけば、重複は私が行方不明になっているので、私は重複を見ている理由についてのフィードバックを感謝します。補足として、テキストボックスの1つのデータが変更されると、行の合計も更新する必要があるため、別の方法が必要になる可能性があります。最初はこの特定の状況を理解することに興味がありますが、潜在的に多くの行が存在する可能性があるため、間違いなく複製を望まないでください。ここで

は例です:http://jsfiddle.net/dwahlin/Y7XbY/2/

+0

これはすぐには分かっていないかもしれませんが、これはhttp://stackoverflow.com/q/14973792/259038の複製です。 –

+0

ありがとうございました。検索にかなり時間を費やしましたが、それを見ませんでした。情報を感謝します。 –

+0

ええ、これは間違いなく、同じケースであることが明らかではないので、これを「削除する」種類の複製ではありません。私は、今後の視聴者のためにループを閉じたいと思っていました。 –

答えて

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

ありがとうございました - それはそれを行うだろうとは思わなかったが、理にかなっている。 –

+0

正直なところ「大したこと」ではないでしょう。それはクライアント側のアプリであり、ユーザーは1人しかいないため、パフォーマンス上の問題が発生していない場合は、維持しやすい方が良い場合は退室することができます。それにもかかわらず、私は答えに提案された修正のための擬似コードをいくつか持っています。 –

+0

+1なぜここで 'angular.forEach'を使わなかったのですか?コードをちょっと切ったような感じです。また、式はすべてのダイジェスト中に*少なくとも1回呼び出されることに注意してください。何回何回保証することはできません。 –

0

最近同様の問題。

各サブオブジェクトを反復処理し、合計をモデルにバインドしました。特に表示目的で合計を使用している場合は、問題ではありません。

例えば、

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

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

各行を繰り返します。

+4

AngularJSプロジェクトの多くはjQueryを使用していませんが、機能的には同様の 'angular.forEach'を使用することができます。 –

1

@Ben Leshのように関数式にバインドしているからです。 何とか$ watchを使っても同じ機能を2回実行してしまいました。 私たちが使用した二重実行を控える解決策は、関数呼び出しに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でも試してみません。しかし、私はそれが動作するはずです。

関連する問題