Come rimuovere un elemento da un array nell'ambito di AngularJS?


153

Elenco di cose da fare semplice, ma con un pulsante Elimina nella pagina elenco per ciascun elemento:

inserisci qui la descrizione dell'immagine

HTML modello pertinente:

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

Metodo del controller pertinente:

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

Ho provato $scope.persons.pull(person)e $scope.persons.remove(person).

Sebbene il database sia stato eliminato correttamente, non riesco a estrarre questo elemento dall'ambito e non voglio effettuare una chiamata di metodo al server per i dati già presenti sul client, desidero solo rimuovere questa persona dall'ambito.

Qualche idea?


Corro con $ route e la vista non funzionerà bene. Ho sempre avuto una pagina vuota dopo aver eliminato :-(
zx1986


non si tratta tanto di cancellare dall'ambito ma piuttosto di un array, e sarebbe lo stesso indipendentemente
dall'angolare

Risposte:


259

Il tuo problema non è proprio con Angular, ma con i metodi Array. Il modo corretto di rimuovere un particolare elemento da un array è con Array.splice. Inoltre, quando si utilizza ng-repeat, si ha accesso alla $indexproprietà speciale , che è l'indice corrente dell'array in cui si è passati.

La soluzione è in realtà piuttosto semplice:

Visualizza:

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

controller:

$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 Hai ragione. Ho dimenticato quella parte. Ho rivisto la mia risposta per rispecchiarla, quindi sarà coerente con la tua.
Josh David Miller,

13
Attenzione: questa soluzione basata su indice non funzionerà se si utilizzano più ng-ripetizioni dello stesso oggetto in una vista (ad es. Attività pianificate, Attività non pianificate, Attività completate tutte provenienti da $ scope.tasks) perché si avranno più elementi con indice 2, 3, 4, ecc.
shacker

Il commento sopra, di @shacker, su più ripetizioni ng con diversi set filtrati dello stesso array, è giusto. Usa il metodo seguente con indexOf
Andrew Kuklewicz,

4
@AndrewKuklewicz - indexOfpuò essere un'operazione più costosa; senza filtro, è completamente inutile. Ma con il filtro, indexOfsarebbe il metodo appropriato.
Josh David Miller,

Sto lottando con questo e ho dovuto apportare una piccola modifica alla generazione del tag sopra - essere - eliminare ({{$ index}}) con {{}} altrimenti ho ottenuto la stringa $ index - MA ho qualcosa di sbagliato perché non chiama mai quel metodo. Lo fa quando rimuovo qualsiasi menzione dell'indice come delete () ma questo non aiuta davvero.
Mikemil,

310

Dovrai trovare l'indice di personnel tuo personsarray, quindi utilizzare il splicemetodo dell'array :

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

49
questa è una risposta migliore; funziona quando l'elenco è stato filtrato in modo tale che l'indice nella vista non sia lo stesso dell'array nell'ambito.
Andrew Kuklewicz,

5
Questa è davvero la risposta migliore. Si noti che oltre agli elenchi filtrati utilizzare il caso menzionato da Andrew, questo approccio copre anche il caso in cui si eliminano più persone e le richieste Ajax per queste eliminazioni tornano fuori servizio. Se hai utilizzato gli indici di riga prima del ritorno della chiamata Ajax, finirai per rimuovere le righe sbagliate.
Joris,

4
È meglio in alcuni casi, ma con indexOf devi iterare su tutti gli elementi per trovare quello giusto, nella risposta di Josh ottieni l'indice e l'oggetto più velocemente
daver


8

Vorrei utilizzare la libreria Underscore.js che ha un elenco di funzioni utili.

without

without_.without(array, *values)

Restituisce una copia dell'array con tutte le istanze dei valori rimossi.

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

Esempio

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

Vedi la demo in JSFiddle .


filter

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

// => [2, 4, 6]

Esempio

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

Vedi la demo in Fiddle .


Probabilmente userei $scope.nodes = _.without($scope.nodes, node);perché ha riferimento alnode
jake

Sui browser moderni puoi usare Array.prototype.filter. _.filter(array, fun)diventa array.filter(fun).
bfontaine,

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

questo funziona per me!


4

Se hai una funzione associata all'elenco, quando esegui la funzione di giunzione, anche l'associazione viene eliminata. La mia soluzione:

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

Il parametro list è denominato items . Il parametro x.done indica se l'elemento verrà eliminato.

Un altro riferimento: un altro esempio

Spero di aiutarti. Saluti.


2

Per la risposta accettata di @Joseph Silber non funziona, perché indexOf restituisce -1. Questo probabilmente perché Angular aggiunge un hashkey, che è diverso per il mio $ scope.items [0] e il mio oggetto. Ho provato a risolverlo con la funzione angular.toJson (), ma non ha funzionato :(

Ah, ho scoperto il motivo ... Uso un metodo chunk per creare due colonne nella mia tabella guardando i miei $ scope.it. Scusa!


2

Puoi anche usare questo

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

1

Angular ha una funzione integrata chiamata arrayRemove, nel tuo caso il metodo può essere semplicemente:

arrayRemove($scope.persons, person)


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.