2016-07-11 8 views
2

私はtrack by $indexを使用しています。なぜなら、配列内に繰り返し要素を許可したいからです。同時に、このコレクションから要素を削除するときに副作用が発生します。

私はコントローラーで$scope.players = []と宣言されているこのプレーヤーのセットを持っています。

<input type="text" ng-model="player"> 
<button ng-click="addPlayer()"> 

addPlayer()はちょうどplayers配列にplayerモデルをプッシュ:

$scope.addPlayer = function() { 
    if (!$scope.player) 
     return; 
    $scope.players.push($scope.player); 
    $scope.player = null; 
}; 

を、コレクションには、ng-repeatを使用して示されている

次のようにして、この配列を移入することができます。しかし、アイテムをクリックしたときにも削除する必要があります。

<div ng-repeat="player in players track by $index" ng-click="deletePlayer($index)"> 
    {{player}} 
</div> 

$scope.deletePlayer = function(index) { 
    if (index > -1) 
     $scope.players.splice(index, 1); 
}; 

問題は、要素がコレクションが変更されたため、選手たちのコレクションは1で短くなります削除されたとき以来、それは、インデックスによって追跡だということです。

私がこれを意味するのは、次のとおりです。プレイヤーの配列["p1", "p2", "p3"]があるとします。 p1などの最後のものを除いてこれらのうちの1つを削除すると、p3が表示されますが、と表示されていても、は[p2, p3]と表示されません。これは、コレクションが1つの要素が短いと言うとき、私が意味することです。

track by $indexモードのng-repeatでは、配列の長さが変更されていないため、問題が発生したと思います。したがって、変更された配列を反復処理する際に、古いインデックスを使用しているため、1つの要素をスキップしています。

この副作用に対処する標準的な方法はありますか?

+0

「コレクションが変更されたため、プレイヤーのコレクションが削除されました」という説明がありますか?アイテムをスプライスした後、またはその前に? –

+0

はい、私の質問を編集させてください。 – dabadaba

答えて

0

問題は、あなたのdeletePlayer関数にあります。引数名は 'i'ですが、代わりに 'index'を使用しようとしています。

この:要素で

$scope.deletePlayer = function(i) { 
    if (i > -1) 
    $scope.players.splice(i, 1); 
}; 
+0

明らかにタイプミスでした...それは本当の問題ではありません – dabadaba

+0

@ダバダバ - しかし、入力を修正することによって、あなたの機能が動作します。少なくともそれはこのプランカーで行いますhttps://plnkr.co/edit/qo3NF8SW79ZUH3y5b0ZN?p=info – jbrown

0

あなたが使用できます:

$scope.deletePlayer = function(i) { 
    if (i > -1) 
    $scope.players.splice(index, 1); 
}; 

があるべきng-click="remove(phones, $index)

を、コードで:

$scope.remove = function(array, index){ 
    array.splice(index, 1); 
} 

あなたはshouldn」任意のpを持つこのアプローチでは厄介です。

0

プレーヤー配列の各アイテムを、nameidのプロパティを持つオブジェクトにすることができます。 Demo

Object.assign($scope, { 
    players: [], 
    player: '', 
    addPlayer: function() { 
    if(!$scope.player) { 
     return 
    } 

    $scope.players = $scope.players.concat({ 
     name: $scope.player, 
     id: Date.now() //fake id (timestamp) 
    }) 

    $scope.player = '' 
    }, 

    deletePlayer: function(id) { 
    $scope.players = $scope.players.filter(function(player){ 
     return player.id !== id 
    }) 
    } 
}) 

    <div ng-repeat="player in players track by player.id" ng-click="deletePlayer(player.id)"> 
    {{player.name}} 
    </div> 
+0

私は範囲に要素を割り当てるこの方法を知らなかった。ニース:) – developer033

+0

@ developer033実際、これは現代のブラウザでのみ機能します。 [angular.extend](https://docs.angularjs.org/api/ng/function/angular.extend)は、より生産性の高い方法です。 –

+0

おかげさまで、@ゆりタラバンコ – developer033

関連する問題