Jak usunąć element z tablicy w zakresie AngularJS?


153

Prosta lista rzeczy do zrobienia, ale z przyciskiem usuwania na stronie listy dla każdego elementu:

wprowadź opis obrazu tutaj

Odpowiedni kod HTML szablonu:

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

Odpowiednia metoda kontrolera:

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

Próbowałem $scope.persons.pull(person)i $scope.persons.remove(person).

Chociaż baza danych została pomyślnie usunięta, nie mogę wyciągnąć tego elementu z zakresu i nie chcę wykonywać wywołania metody do serwera w celu uzyskania danych, które klient już posiada, po prostu chcę usunąć tę jedną osobę z zakresu.

Jakieś pomysły?


Uruchamiam tę odrobinę trasy $, a widok nie będzie działał dobrze. Zawsze otrzymywałem pustą stronę po usunięciu :-(
zx1986


nie chodzi tu tak bardzo o usuwanie z zakresu, ale raczej z tablicy i byłoby tak samo niezależnie od kąta, tylko javascript
Xsmael

Odpowiedzi:


259

Twój problem nie dotyczy tak naprawdę Angulara, ale metod Array. Właściwym sposobem usunięcia konkretnego elementu z tablicy jest Array.splice. Ponadto, używając ng-repeat, masz dostęp do specjalnej $indexwłaściwości, którą jest bieżący indeks przekazanej tablicy.

Rozwiązanie jest w rzeczywistości dość proste:

Widok:

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

Kontroler:

$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 Masz rację. Zapomniałem o tej części. Poprawiłem swoją odpowiedź, aby to odzwierciedlić, aby była zgodna z twoją.
Josh David Miller,

13
Ostrożnie - to rozwiązanie oparte na indeksach nie zadziała, jeśli w widoku użyjesz wielu powtórzeń ng tego samego obiektu (np. Zaplanowane zadania, Niezaplanowane zadania, Ukończone zadania, wszystkie wychodzące z $ scope.tasks), ponieważ będziesz mieć wiele elementów z indeks 2, 3, 4 itd.
shacker

Komentarz powyżej, autorstwa @shacker, dotyczący wielu powtórzeń ng z różnymi filtrowanymi zestawami tej samej tablicy, jest tuż obok. Użyj poniższej metody z indexOf
Andrew Kuklewicz

4
@AndrewKuklewicz - operacja indexOfmoże być droższa; bez filtrowania jest to całkowicie niepotrzebne. Ale z filtrowaniem indexOfbyłaby odpowiednia metoda.
Josh David Miller

Zmagam się z tym i musiałem dokonać drobnej zmiany w generowaniu tagu powyżej - będąc - usuń ({{$ index}}) z {{}} w przeciwnym razie otrzymałem ciąg $ index - ALE mam coś nie tak, ponieważ to nigdy nie wywołuje tej metody. Dzieje się tak, gdy usuwam wszelkie wzmianki o indeksie, takie jak delete (), ale to naprawdę nie pomaga.
mikemil

310

Będziesz musiał znaleźć indeks tablicy personw swojej personstablicy, a następnie użyć metody tablicy splice:

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

49
to jest lepsza odpowiedź; działa, gdy lista została przefiltrowana, więc indeks w widoku nie jest taki sam jak w tablicy w zakresie.
Andrew Kuklewicz

5
To jest rzeczywiście lepsza odpowiedź. Zauważ, że oprócz przypadków użycia list filtrowanych, o których wspomniał Andrew, to podejście obejmuje również przypadek, w którym usuwasz wiele osób, a żądania Ajax dotyczące tych usunięć wracają poza kolejnością. Jeśli użyłeś indeksów wierszy sprzed powrotu wywołania Ajax, w końcu usuniesz niewłaściwe wiersze.
Joris

4
W niektórych przypadkach jest lepsze, ale z indexO Jeśli musisz iterować po wszystkich elementach, aby znaleźć właściwy, w odpowiedzi Josha otrzymasz indeks i element szybciej
daver


8

Chciałbym użyć underscore.js bibliotekę, która ma listę przydatnych funkcji.

without

without_.without(array, *values)

Zwraca kopię tablicy z usuniętymi wszystkimi wystąpieniami wartości.

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

Przykład

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

Zobacz Demo w JSFiddle .


filter

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

// => [2, 4, 6]

Przykład

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

Zobacz demo w Fiddle .


Prawdopodobnie użyłbym, $scope.nodes = _.without($scope.nodes, node);ponieważ ma odniesienie donode
jake

W nowoczesnych przeglądarkach możesz używać Array.prototype.filter. _.filter(array, fun)staje się array.filter(fun).
bfontaine,

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

to działa dla mnie!


4

Jeśli masz jakąś funkcję skojarzoną z listą, podczas tworzenia funkcji łączenia, skojarzenie również zostanie usunięte. Moje rozwiązanie:

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

Parametr listy nosi nazwę items . Parametr x.done wskazuje, czy element zostanie usunięty.

Inne odniesienia: inny przykład

Mam nadzieję, że ci pomogę. Pozdrowienia.


2

Dla zaakceptowanej odpowiedzi @Joseph Silber nie działa, ponieważ indexOf zwraca -1. Dzieje się tak prawdopodobnie dlatego, że Angular dodaje klucz skrótu, który jest inny dla mojego $ scope.items [0] i dla mojego elementu. Próbowałem rozwiązać ten problem za pomocą funkcji angular.toJson (), ale to nie zadziałało :(

Ach, znalazłem przyczynę ... Używam metody fragmentów, aby utworzyć dwie kolumny w mojej tabeli, obserwując moje $ scope.items. Przepraszam!


2

Możesz również użyć tego

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

1

Angular ma wbudowaną funkcję o nazwie arrayRemove, w twoim przypadku metodą może być po prostu:

arrayRemove($scope.persons, person)


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.