2016-07-11 10 views
2

Ich verwende track by $index, weil ich wiederholte Elemente in meinem Array zulassen möchte, aber gleichzeitig verursacht dies einen Nebeneffekt beim Entfernen von Elementen aus dieser Sammlung.

Ich habe diese Gruppe von Spielern, die in der Steuerung als $scope.players = [] deklariert ist.

können Sie dieses Array wie folgt benutzt:

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

addPlayer() schiebt nur das player Modell zum players Array:

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

und die Sammlung wird mit ng-repeat gezeigt. Aber auch wenn ein Gegenstand angeklickt wird, sollte er gelöscht werden.

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

Das Problem ist, dass, da es durch den Index Tracking, wenn ein Element der Sammlung von Spielern entfernt wird um 1 kurz sein, weil die Sammlung verändert hat.

Was ich damit meine, ist folgendes: sagen, ich habe das Array von Spielern ["p1", "p2", "p3"]. Wenn ich eine davon mit Ausnahme der letzten entferne, zum Beispiel p1, zeigt die ng-repeat nicht [p2, p3], obwohl dies der Inhalt des Arrays ist, aber es zeigt nur p3. Das ist was ich meine, wenn ich sage, dass die Sammlung ein Element kurz ist.

Ich denke, das Problem passiert, weil ng-repeat im track by $index-Modus unbekannt ist, dass die Länge des Arrays geändert hat. Daher überspringt es ein Element beim Iterieren durch das geänderte Array, weil es die alten Indizes verwendet, um es zu iterieren, glaube ich.

Gibt es eine Standardmethode zur Bewältigung dieses Nebeneffekts?

+0

Können Sie erklären, dass "die Sammlung von Spielern um 1 reduziert wurde, weil sich die Sammlung geändert hat." nachdem du den Gegenstand gespleißt hast oder vorher? –

+0

Ja, lass mich meine Frage bearbeiten. – dabadaba

Antwort

0

Das Problem ist mit Ihrer deletePlayer-Funktion. Ihr Argumentname ist "i", aber Sie versuchen stattdessen, "index" zu verwenden.

Dieses:

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

sollte sein:

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

das war offensichtlich ein Tippfehler ...es ist nicht das eigentliche Problem – dabadaba

+0

@dabadaba - Ok, aber durch die Fixierung des Tippfehlers Ihre Funktion funktioniert. Zumindest tut es in diesem Fall https://plnrkr.co/edit/qo3NF8SW79ZUH3y5b0ZN?p=info – jbrown

0

Im Element könnten Sie: ng-click="remove(phones, $index)

Und im Code:

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

Sie shouldn‘ t haben irgendwelche p Probleme mit diesem Ansatz.

0

Sie können jedes Element im Player-Array zu einem Objekt mit den Eigenschaften name und id machen. Demo.

+0

Ich kannte diese Art der Zuordnung von Elementen zum Geltungsbereich nicht. Nice :) – developer033

+0

@ developer033 Eigentlich funktioniert das nur in modernen Browsern. [angular.extend] (https://docs.angularjs.org/api/ng/function/angular.extend) ist mehr produktionsfertig. –

+0

Danke für die Info, @ Yuri Tarabanko – developer033