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.