Wie entferne ich ein Element aus einem Array im AngularJS-Bereich?


153

Einfache Aufgabenliste, jedoch mit einer Schaltfläche zum Löschen auf der Listenseite für jedes Element:

Geben Sie hier die Bildbeschreibung ein

Relevante Vorlage HTML:

<tr ng-repeat="person in persons">
  <td>{{person.name}} - # {{person.id}}</td>
  <td>{{person.description}}</td>
  <td nowrap=nowrap>
    <a href="#!/edit"><i class="icon-edit"></i></a>
    <button ng-click="delete(person)"><i class="icon-minus-sign"></i></button>
  </td>
</tr>

Relevante Controller-Methode:

$scope.delete = function (person) {
  API.DeletePerson({ id: person.id }, function (success) {
    // I need some code here to pull the person from my scope.
  });
};

Ich habe es versucht $scope.persons.pull(person)und $scope.persons.remove(person).

Obwohl die Datenbank erfolgreich gelöscht wurde, kann ich dieses Element nicht aus dem Bereich ziehen und möchte keinen Methodenaufruf an den Server für Daten senden, über die der Client bereits verfügt. Ich möchte nur diese eine Person aus dem Bereich entfernen.

Irgendwelche Ideen?


Ich führe diese weiße Route aus, und die Ansicht funktioniert nicht einwandfrei. Ich habe nach dem Löschen immer eine leere Seite bekommen :-(
zx1986

Habe einen ähnlichen Artikel geschrieben codepedia.info/angularjs-delete-table-row-tr-on-click
Satinder singh

Hier geht es nicht so sehr um das Löschen aus dem Bereich, sondern vielmehr aus einem Array, und es wäre unabhängig vom Winkel dasselbe, es ist nur Javascript
Xsmael

Antworten:


259

Ihr Problem liegt nicht wirklich bei Angular, sondern bei Array-Methoden. Der richtige Weg, um ein bestimmtes Element aus einem Array zu entfernen, ist mit Array.splice. Wenn Sie ng-repeat verwenden, haben Sie außerdem Zugriff auf die spezielle $indexEigenschaft, bei der es sich um den aktuellen Index des Arrays handelt, das Sie übergeben haben.

Die Lösung ist eigentlich ziemlich einfach:

Aussicht:

<a ng-click="delete($index)">Delete</a>

Regler:

$scope.delete = function ( idx ) {
  var person_to_delete = $scope.persons[idx];

  API.DeletePerson({ id: person_to_delete.id }, function (success) {
    $scope.persons.splice(idx, 1);
  });
};

1
@ ScottMalachowski Du hast recht. Ich habe diesen Teil vergessen. Ich habe meine Antwort überarbeitet, um dies widerzuspiegeln, damit sie mit Ihrer übereinstimmt.
Josh David Miller

13
Vorsicht - Diese indexbasierte Lösung funktioniert nicht, wenn Sie mehrere ng-Wiederholungen desselben Objekts in einer Ansicht verwenden (z. B. geplante Aufgaben, außerplanmäßige Aufgaben, abgeschlossene Aufgaben, die alle aus $ scope.tasks stammen), da Sie mehrere Elemente mit haben Index 2, 3, 4 usw.
Shacker

Der obige Kommentar von @shacker zu mehreren ng-Wiederholungen mit verschiedenen gefilterten Sätzen desselben Arrays ist richtig. Verwenden Sie die Methode unten mit indexOf
Andrew Kuklewicz

4
@ AndrewKuklewicz - indexOfkann eine teurere Operation sein; ohne Filterung ist das völlig unnötig. Aber mit Filterung indexOfwäre die geeignete Methode.
Josh David Miller

Ich habe damit zu kämpfen und musste eine geringfügige Änderung an der obigen Tag-Generierung vornehmen - Sein - Löschen ({{$ index}}) mit dem {{}}, sonst habe ich den String $ index - ABER ich habe etwas falsch gemacht, weil es ruft diese Methode niemals auf. Es funktioniert, wenn ich eine Erwähnung des Index wie delete () entferne, aber das hilft nicht wirklich.
Mikemil

310

Sie müssen den Index von personin Ihrem personsArray finden und dann die spliceMethode des Arrays verwenden:

$scope.persons.splice( $scope.persons.indexOf(person), 1 );

49
das ist eine bessere Antwort; funktioniert, wenn die Liste so gefiltert wurde, dass dieser Index in der Ansicht nicht mit dem im Bereich des Arrays übereinstimmt.
Andrew Kuklewicz

5
Dies ist in der Tat die bessere Antwort. Beachten Sie, dass dieser Ansatz zusätzlich zu dem von Andrew erwähnten Anwendungsfall für gefilterte Listen auch den Fall abdeckt, in dem Sie mehrere Personen löschen und die Ajax-Anforderungen für diese Löschvorgänge nicht in der richtigen Reihenfolge zurückgegeben werden. Wenn Sie die Zeilenindizes vor der Rückkehr des Ajax-Aufrufs verwendet haben, werden am Ende die falschen Zeilen entfernt.
Joris

4
Ist in einigen Fällen besser, aber mit indexOf müssen Sie alle Elemente durchlaufen, um das richtige zu finden. In der Josh-Antwort erhalten Sie den Index und das Element schneller
daver

@mike - Verwenden Sie diese Polyfüllung .
Joseph Silber

8

Ich würde die Bibliothek Underscore.js verwenden, die eine Liste nützlicher Funktionen enthält.

without

without_.without(array, *values)

Gibt eine Kopie des Arrays zurück, wobei alle Instanzen der Werte entfernt wurden.

_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
// => [2, 3, 4]

Beispiel

var res = "deleteMe";

$scope.nodes = [
  {
    name: "Node-1-1"
  },
  {
    name: "Node-1-2"
  },
  {
    name: "deleteMe"
  }
];
    
$scope.newNodes = _.without($scope.nodes, _.findWhere($scope.nodes, {
  name: res
}));

Siehe Demo in JSFiddle .


filter

var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });

// => [2, 4, 6]

Beispiel

$scope.newNodes = _.filter($scope.nodes, function(node) {
  return !(node.name == res);
});

Siehe Demo in Fiddle .


Ich würde wahrscheinlich verwenden, $scope.nodes = _.without($scope.nodes, node);weil er Bezug auf dienode
Jake

Auf modernen Browsern können Sie verwenden Array.prototype.filter. _.filter(array, fun)wird array.filter(fun).
Bfontaine

7
$scope.removeItem = function() {
    $scope.items.splice($scope.toRemove, 1);
    $scope.toRemove = null;
};

das funktioniert bei mir!


4

Wenn der Liste eine Funktion zugeordnet ist, wird beim Ausführen der Spleißfunktion auch die Zuordnung gelöscht. Meine Lösung:

$scope.remove = function() {
    var oldList = $scope.items;
    $scope.items = [];

    angular.forEach(oldList, function(x) {
        if (! x.done) $scope.items.push( { [ DATA OF EACH ITEM USING oldList(x) ] });
    });
};

Der Listenparameter heißt Elemente . Der Parameter x.done gibt an, ob das Element gelöscht wird.

Weitere Referenzen: Ein weiteres Beispiel

Hoffe dir zu helfen. Schöne Grüße.


2

Für die akzeptierte Antwort von @Joseph Silber funktioniert das nicht, da indexOf -1 zurückgibt. Dies liegt wahrscheinlich daran, dass Angular einen Hashkey hinzufügt, der sich für mein $ scope.items [0] und mein Element unterscheidet. Ich habe versucht, dies mit der Funktion angle.toJson () zu beheben, aber es hat nicht funktioniert :(

Ah, ich habe den Grund herausgefunden ... Ich verwende eine Chunk-Methode, um zwei Spalten in meiner Tabelle zu erstellen, indem ich meine $ scope.items beobachte. Es tut uns leid!


2

Sie können dies auch verwenden

$scope.persons = $filter('filter')($scope.persons , { id: ('!' + person.id) });

1

Angular hat eine eingebaute Funktion namens arrayRemove, in Ihrem Fall kann die Methode einfach sein:

arrayRemove($scope.persons, person)


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.