Come posso eliminare un oggetto o un oggetto da un array usando ng-click?


261

Sto cercando di scrivere una funzione che mi consente di rimuovere un elemento quando si fa clic sul pulsante, ma penso che mi sto confondendo con la funzione: devo usare $digest?

HTML e app.js:

<ul ng-repeat="bday in bdays">
  <li>
    <span ng-hide="editing" ng-click="editing = true">{{bday.name}} | {{bday.date}}</span>
    <form ng-show="editing" ng-submit="editing = false">
      <label>Name:</label>
      <input type="text" ng-model="bday.name" placeholder="Name" ng-required/>
      <label>Date:</label>
      <input type="date" ng-model="bday.date" placeholder="Date" ng-required/>
      <br/>
      <button class="btn" type="submit">Save</button>
      <a class="btn" ng-click="remove()">Delete</a>
    </form>
  </li>
</ul>

$scope.remove = function(){
  $scope.newBirthday = $scope.$digest();
};

2
Non vuoi $ digest, poiché questo è usato per entrare nel ciclo digest di Angular (e sei già in un ciclo digest a causa del ng-click). Stai cercando di rimuovere un elemento da un array?
Mark Rajcok,

@MarkRajcok :) Sì, è quello che sto cercando di fare
Jess McKenzie

remove()nel ng-clickmodo in cui lo hai non ha contesto. Hai bisogno di maggiori dettagli nel markup per mostrare cosa viene rimosso e se si trova all'interno ng-repeat, o da dove proviene l'elemento rimosso o da quale comportamento desideriremove()
charlietfl

@charlietfl è dentro ng-repeat ho aggiornato la domanda
Jess McKenzie

Ecco il mio 1 articolo che spiega come eliminare i record con ng-repeat codepedia.info/angularjs-delete-table-row-tr-on-click
Satinder singh

Risposte:


552

Per rimuovere l'elemento è necessario rimuoverlo dall'array e è possibile passare l' bdayelemento alla funzione di rimozione nel markup. Quindi nel controller cercare l'indice dell'elemento e rimuoverlo dall'array

<a class="btn" ng-click="remove(item)">Delete</a>

Quindi nel controller:

$scope.remove = function(item) { 
  var index = $scope.bdays.indexOf(item);
  $scope.bdays.splice(index, 1);     
}

Angular rileverà automaticamente la modifica bdaysdell'array e eseguirà l'aggiornamento ding-repeat

DEMO: http://plnkr.co/edit/ZdShIA?p=preview

MODIFICA: se si eseguono aggiornamenti in tempo reale con il server, si utilizza un servizio creato $resourceper gestire gli aggiornamenti dell'array contemporaneamente al server di aggiornamento


62
L'uso $indexdiretto può generare bug se la tua lista è filtrata su template. È una cosa modello; è più sicuro da usare ng-click='remove(bday)'alloraarr.splice(arr.indexOf(bday),1);
Umur Kontacı

6
Non è necessario passare $ index perché è possibile utilizzare "this" all'interno del metodo. $ scope.remove = function () {$ scope.bdays.splice (questo. $ index, 1); }
matchdav

1
@matthewdavidson this is undefined. Plunker / jsfiddle forse?
Tjorriemorrie,

11
.indexOf(item)restituirà -1 se non trovato, ciò potrebbe comportare la rimozione dell'elemento alla fine dell'array se non lo si controlla.
Ben Wilde,

1
@ShibinRagh leggi i documenti per Array.prototype.splice ()
charlietfl

54

Questa è una risposta corretta:

<a class="btn" ng-click="remove($index)">Delete</a>
$scope.remove=function($index){ 
  $scope.bdays.splice($index,1);     
}

Nella risposta di @ charlietfl. Penso che sia sbagliato dal momento che passi $indexcome parametro ma usi invece il desiderio nel controller. Correggimi se sbaglio :)


sembra che entrambe le risposte siano equivalenti, anche se la tua funzione può accettare l'indice senza $ e funzionerà comunque.
svarog

questa dovrebbe essere la risposta corretta. indexOfFunziona SOLO se è IE9 +
levi

17
Questo non funzionerà se hai un ordine per o un filtro nel tuo ng-repeat
Joan-Diego Rodriguez,

Funzionerà meglio se hai utilizzato la traccia di $ index
Ankit Balyan il

@ Joan-DiegoRodriguez Come faresti a farlo funzionare se si dispone di un filtro / ordine Non importa basta leggere la risposta di
XMLilley

26

Nel caso in cui ti trovi in ​​una ripetizione ng

potresti usare un'opzione di una fodera

    <div ng-repeat="key in keywords"> 
        <button ng-click="keywords.splice($index, 1)">

            {{key.name}}
        </button>
    </div>

$index viene utilizzato da angolare per mostrare l'indice corrente dell'array all'interno ng-repeat


1
Mi piace e ho usato questa fodera
etoricky il

24

L'uso $indexfunziona perfettamente nei casi di base e la risposta di @ charlietfl è ottima. Ma a volte $indexnon è abbastanza.

Immagina di avere un solo array, che stai presentando in due diverse repliche. Uno di questi ng-repeat è filtrato per oggetti che hanno una proprietà true, e l'altro è filtrato per una proprietà falsy. Vengono presentati due diversi array filtrati, che derivano da un singolo array originale. (Oppure, se aiuta a visualizzare: forse hai un solo array di persone e vuoi una ng-repeat per le donne in quell'array e un'altra per gli uomini in quello stesso array .) Il tuo obiettivo: eliminare in modo affidabile dal array originale, utilizzando le informazioni dai membri degli array filtrati.

In ognuna di quelle matrici filtrate, $ index non sarà l'indice dell'elemento all'interno dell'array originale. Sarà l'indice nell'array secondario filtrato . Quindi, non sarà in grado di dire indice della persona in originale peoplematrice, saprete solo l'indice $ dal womeno mensub-array. Prova a eliminarlo usando quello e avrai oggetti che spariscono da ogni parte tranne dove volevi. Cosa fare?

Se sei abbastanza fortunato, l'utilizzo di un modello di dati include un identificatore univoco per ciascun oggetto, quindi utilizza quello invece di $ index per trovare l'oggetto e splicel'array fuori dall'array principale. (Usa il mio esempio qui sotto, ma con quell'identificatore univoco.) Ma se non sei così fortunato?

Angular aumenta effettivamente ogni elemento in una matrice ripetuta ng (nella matrice principale originale) con una proprietà unica chiamata $$hashKey. Puoi cercare nell'array originale una corrispondenza $$hashKeydell'elemento che desideri eliminare e liberartene in quel modo.

Si noti che $$hashKeyè un dettaglio dell'implementazione, non incluso nell'API pubblicata per ng-repeat. Potrebbero rimuovere il supporto per quella proprietà in qualsiasi momento. Ma probabilmente no. :-)

$scope.deleteFilteredItem = function(hashKey, sourceArray){
  angular.forEach(sourceArray, function(obj, index){
    // sourceArray is a reference to the original array passed to ng-repeat, 
    // rather than the filtered version. 
    // 1. compare the target object's hashKey to the current member of the iterable:
    if (obj.$$hashKey === hashKey) {
      // remove the matching item from the array
      sourceArray.splice(index, 1);
      // and exit the loop right away
      return;
    };
  });
}

Invocare con:

ng-click="deleteFilteredItem(item.$$hashKey, refToSourceArray)"

MODIFICA: L'uso di una funzione come questa, che consente di utilizzare il tasto $$hashKeyanziché il nome di una proprietà specifica del modello, ha anche il significativo vantaggio aggiuntivo di rendere questa funzione riutilizzabile in diversi modelli e contesti. Forniscilo con il riferimento dell'array e il riferimento dell'articolo e dovrebbe funzionare.


10

Di solito scrivo in tale stile:

<a class="btn" ng-click="remove($index)">Delete</a>


$scope.remove = function(index){
  $scope.[yourArray].splice(index, 1)
};

Spero che questo ti sia d'aiuto Devi usare un punto (.) Tra $ scope e [yourArray]


Qual è il significato di "1" in (indice, 1)
ShibinRagh il

@ShibinRagh È il deleteCount. Un numero intero che indica il numero di vecchi elementi dell'array da rimuovere. Se deleteCount è 0, nessun elemento viene rimosso. In questo caso, è necessario specificare almeno un nuovo elemento. Se deleteCount è maggiore del numero di elementi rimasti nell'array a partire dall'inizio, tutti gli elementi fino alla fine dell'array verranno eliminati. Documentazione di Array.prototype.splice ()
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ

9

Sulla base la risposta accettata, questo funzionerà con ngRepeat, filtere maniglia expections meglio:

controller:

vm.remove = function(item, array) {
  var index = array.indexOf(item);
  if(index>=0)
    array.splice(index, 1);
}

Visualizza:

ng-click="vm.remove(item,$scope.bdays)"

Non hai assegnato, "rimuovi" a $ scope.vm nel tuo controller, quindi questo codice non funzionerebbe. Ora se lo facessi ... $ scope.vm = {remove: function () {...}}, lo farebbe.
Justin Russo,

4

implementazione senza controller.

<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>

<script>
  var app = angular.module("myShoppingList", []); 
</script>

<div ng-app="myShoppingList"  ng-init="products = ['Milk','Bread','Cheese']">
  <ul>
    <li ng-repeat="x in products track by $index">{{x}}
      <span ng-click="products.splice($index,1)">×</span>
    </li>
  </ul>
  <input ng-model="addItem">
  <button ng-click="products.push(addItem)">Add</button>
</div>

<p>Click the little x to remove an item from the shopping list.</p>

</body>
</html>

Il metodo splice () aggiunge / rimuove elementi da / verso un array.

array.splice(index, howmanyitem(s), item_1, ....., item_n)

indice : obbligatorio. Un numero intero che specifica in quale posizione aggiungere / rimuovere gli elementi, utilizzare valori negativi per specificare la posizione dalla fine dell'array.

howmanyitem (s) : facoltativo. Il numero di elementi da rimuovere. Se impostato su 0, nessun elemento verrà rimosso.

item_1, ..., item_n : opzionale. I nuovi elementi da aggiungere all'array


1
Questa è la risposta esatta. Perché affidarsi a un controller per eseguire semplici chiamate JavaScript?
Elle Fie

3

Non sono d'accordo sul fatto che dovresti chiamare un metodo sul tuo controller. Dovresti utilizzare un servizio per qualsiasi funzionalità effettiva e definire le direttive per qualsiasi funzionalità per la scalabilità e la modularità, nonché assegnare un evento click che contenga una chiamata al servizio che hai inserito nella direttiva.

Quindi, ad esempio, sul tuo HTML ...

<a class="btn" ng-remove-birthday="$index">Delete</a>

Quindi, crea una direttiva ...

angular.module('myApp').directive('ngRemoveBirthday', ['myService', function(myService){
    return function(scope, element, attrs){
        angular.element(element.bind('click', function(){
            myService.removeBirthday(scope.$eval(attrs.ngRemoveBirthday), scope);  
        };       
    };
}])

Quindi al tuo servizio ...

angular.module('myApp').factory('myService', [function(){
    return {
        removeBirthday: function(birthdayIndex, scope){
            scope.bdays.splice(birthdayIndex);
            scope.$apply();
        }
    };
}]);

Quando scrivi correttamente il tuo codice in questo modo, renderai molto semplice scrivere modifiche future senza dover ristrutturare il tuo codice. È organizzato correttamente e gestisci correttamente gli eventi di clic personalizzati vincolando tramite direttive personalizzate.

Ad esempio, se il tuo client dice "hey, ora facciamolo chiamare il server e fare il pane, quindi pop-up un modale". Sarai in grado di accedere facilmente al servizio stesso senza dover aggiungere o modificare codice HTML e / o codice del controller. Se avessi solo una linea sul controller, alla fine dovrai utilizzare un servizio, per estendere la funzionalità al sollevamento più pesante richiesto dal client.

Inoltre, se hai bisogno di un altro pulsante 'Elimina' altrove, ora hai un attributo direttiva ('ng-remove-birthday') che puoi facilmente assegnare a qualsiasi elemento della pagina. Questo ora lo rende modulare e riutilizzabile. Ciò sarà utile quando si ha a che fare con il paradigma dei componenti Web HEAVY di Angular 2.0. Non esiste un controller in 2.0. :)

Buon sviluppo !!!



0

se hai un ID o un campo specifico nel tuo articolo, puoi usare filter (). agisce come Where ().

<a class="btn" ng-click="remove(item)">Delete</a>

nel controller:

$scope.remove = function(item) { 
  $scope.bdays = $scope.bdays.filter(function (element) {
                    return element.ID!=item.ID
                });
}

0
Pass the id that you want to remove from the array to the given function 

dal controller (la funzione può essere nello stesso controller ma preferisce tenerlo in un servizio)

    function removeInfo(id) {
    let item = bdays.filter(function(item) {
      return bdays.id=== id;
    })[0];
    let index = bdays.indexOf(item);
    data.device.splice(indexOfTabDetails, 1);
  }
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.