Comment supprimer un élément ou un objet d'un tableau à l'aide de ng-click?


261

J'essaie d'écrire une fonction qui me permet de supprimer un élément lorsque le bouton est cliqué, mais je pense que je suis confus avec la fonction - dois-je utiliser $digest?

HTML et 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
Vous ne voulez pas $ digest, car il est utilisé pour entrer dans la boucle de résumé d'Angular (et vous êtes déjà dans une boucle de résumé à cause du ng-click). Essayez-vous de supprimer un élément d'un tableau?
Mark Rajcok

@MarkRajcok :) oui c'est ce que j'essaie de faire
Jess McKenzie

remove()dans ng-clickla façon dont vous l'avez n'a pas de contexte. Besoin de plus de détails dans le balisage pour montrer ce qui est supprimé et s'il se trouve à l'intérieur ng-repeat, d'où vient l'élément supprimé ou quel comportement vous souhaitezremove()
charlietfl

@charlietfl c'est dans ng-repeat J'ai mis à jour la question
Jess McKenzie

Voici mon 1 article qui explique comment supprimer un enregistrement avec ng-repeat codepedia.info/angularjs-delete-table-row-tr-on-click
Satinder singh

Réponses:


552

Pour supprimer un élément, vous devez le supprimer du tableau et pouvez transmettre l' bdayélément à votre fonction de suppression dans le balisage. Ensuite, dans le contrôleur, recherchez l'index de l'élément et supprimez-le du tableau

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

Puis dans le contrôleur:

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

Angular détectera automatiquement la modification de la bdaysbaie et effectuera la mise à jour deng-repeat

DÉMO: http://plnkr.co/edit/ZdShIA?p=preview

EDIT: si faire des mises à jour en direct avec le serveur utiliserait un service que vous créez en utilisant $resourcepour gérer les mises à jour de la baie en même temps qu'il met à jour le serveur


62
L'utilisation $indexdirecte peut générer des bugs si votre liste est filtrée sur un modèle. C'est une chose modèle; il est plus sûr d'utiliser ng-click='remove(bday)'alorsarr.splice(arr.indexOf(bday),1);
Umur Kontacı

6
Vous n'avez pas besoin de passer $ index car vous pouvez utiliser 'this' dans la méthode. $ scope.remove = function () {$ scope.bdays.splice (this. $ index, 1); }
matchdav

1
@matthewdavidson this is undefined. Plunker / jsfiddle peut-être?
Tjorriemorrie

11
.indexOf(item)renverra -1 s'il n'est pas trouvé, cela pourrait entraîner la suppression de l'élément à la fin du tableau si vous ne le vérifiez pas.
Ben Wilde

1
@ShibinRagh lire les documents pour Array.prototype.splice ()
charlietfl

54

Ceci est une bonne réponse:

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

Dans la réponse de @ charlietfl. Je pense que c'est faux puisque vous passez $indexen paramètre mais vous utilisez plutôt le souhait dans le contrôleur. Corrige moi si je me trompe :)


semble que les deux réponses sont équivalentes, bien que votre fonction puisse accepter l'index sans $ et cela fonctionnera toujours.
svarog

ce devrait être la bonne réponse. indexOfFonctionne UNIQUEMENT si c'est IE9 +
levi

17
Cela ne fonctionnera pas si vous avez une commandePar ou un filtre dans votre ng-repeat
Joan-Diego Rodriguez

Cela fonctionnera mieux, si vous avez utilisé la piste par $ index
Ankit Balyan

@ Joan-DiegoRodriguez Comment feriez-vous pour que cela fonctionne si vous avez un filtre / une commande? Peu importe, lisez simplement la réponse de
XMLilley

26

Dans le cas où vous êtes à l'intérieur d'une répétition ng

vous pouvez utiliser une option de doublure

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

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

$index est utilisé par angulaire pour afficher l'index actuel du tableau à l'intérieur ng-repeat


1
J'aime et j'ai utilisé cette doublure
etoricky

24

L'utilisation $indexfonctionne parfaitement dans les cas de base, et la réponse de @ charlietfl est excellente. Mais parfois, ce $indexn'est pas suffisant.

Imaginez que vous ayez un seul tableau, que vous présentez dans deux ng-répétitions différentes. L'un de ces ng-repeat est filtré pour les objets qui ont une propriété true, et l'autre est filtré pour une propriété falsy. Deux tableaux filtrés différents sont présentés, qui dérivent d'un seul tableau d'origine. (Ou, si cela aide à visualiser: peut-être que vous avez un seul tableau de personnes et que vous voulez une répétition ng pour les femmes de ce tableau et une autre pour les hommes de ce même tableau .) Votre objectif: supprimer de manière fiable du tableau d'origine, en utilisant les informations des membres des tableaux filtrés.

Dans chacun de ces tableaux filtrés, $ index ne sera pas l'index de l'élément dans le tableau d'origine. Ce sera l'index dans le sous-tableau filtré . Ainsi, vous ne pourrez pas dire l'index de la personne dans le peopletableau d' origine , vous ne connaîtrez que l'index $ du womenou du mensous-tableau. Essayez de supprimer en utilisant cela, et vous aurez des éléments disparaissant de partout sauf là où vous le vouliez. Que faire?

Si vous avez la chance d'utiliser un modèle de données comprenant un identifiant unique pour chaque objet, utilisez-le au lieu de $ index, pour trouver l'objet et splicele sortir du tableau principal. (Utilisez mon exemple ci-dessous, mais avec cet identifiant unique.) Mais si vous n'êtes pas aussi chanceux?

Angular augmente en fait chaque élément dans un tableau ng-répété (dans le tableau principal d'origine) avec une propriété unique appelée $$hashKey. Vous pouvez rechercher dans le tableau d'origine une correspondance avec l' $$hashKeyélément que vous souhaitez supprimer et vous en débarrasser de cette façon.

Notez qu'il $$hashKeys'agit d'un détail d'implémentation, non inclus dans l'API publiée pour ng-repeat. Ils pouvaient retirer le support de cette propriété à tout moment. Mais probablement pas. :-)

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

Invoquer avec:

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

EDIT: L'utilisation d'une fonction comme celle-ci, qui clique sur au $$hashKeylieu d'un nom de propriété spécifique au modèle, a également l'avantage supplémentaire significatif de rendre cette fonction réutilisable dans différents modèles et contextes. Fournissez-lui votre référence de tableau et votre référence d'élément, et cela devrait simplement fonctionner.


10

J'écris généralement dans un tel style:

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


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

J'espère que cela vous aidera Vous devez utiliser un point (.) Entre $ scope et [yourArray]


Quelle est la signification de "1" dans (index, 1)
ShibinRagh

@ShibinRagh C'est le deleteCount. Un entier indiquant le nombre d'anciens éléments de tableau à supprimer. Si deleteCount vaut 0, aucun élément n'est supprimé. Dans ce cas, vous devez spécifier au moins un nouvel élément. Si deleteCount est supérieur au nombre d'éléments restant dans le tableau à partir du début, tous les éléments jusqu'à la fin du tableau seront supprimés. Documentation de Array.prototype.splice ()
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ

9

S'appuyant sur la réponse acceptée, cela fonctionnera avec ngRepeat, filteret poignée expections mieux:

Manette:

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

Vue:

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

Vous n'avez pas assigné, "supprimé" à $ scope.vm dans votre contrôleur, donc ce code ne fonctionnerait pas. Maintenant, si vous faisiez cela ... $ scope.vm = {remove: function () {...}}, alors ce serait le cas.
Justin Russo

4

mise en œuvre sans contrôleur.

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

La méthode splice () ajoute / supprime des éléments vers / depuis un tableau.

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

index : obligatoire. Un entier qui spécifie à quelle position ajouter / supprimer des éléments. Utilisez des valeurs négatives pour spécifier la position à partir de la fin du tableau.

howmanyitem (s) : Facultatif. Le nombre d'éléments à supprimer. S'il est défini sur 0, aucun élément ne sera supprimé.

item_1, ..., item_n : facultatif. Le ou les nouveaux éléments à ajouter au tableau


1
Ceci est la bonne réponse. Pourquoi s'appuyer sur un contrôleur pour effectuer de simples appels JavaScript?
Elle Fie

3

Je ne suis pas d'accord pour que vous appeliez une méthode sur votre contrôleur. Vous devez utiliser un service pour toute fonctionnalité réelle, et vous devez définir des directives pour toute fonctionnalité d'évolutivité et de modularité, ainsi que l'attribution d'un événement de clic qui contient un appel au service que vous injectez dans votre directive.

Ainsi, par exemple, sur votre HTML ...

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

Ensuite, créez une directive ...

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

Alors à votre service ...

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

Lorsque vous écrivez correctement votre code comme celui-ci, vous faciliterez l'écriture de modifications futures sans avoir à restructurer votre code. Il est organisé correctement et vous gérez correctement les événements de clic personnalisés en liant à l'aide de directives personnalisées.

Par exemple, si votre client dit: "Hé, maintenant faisons-le appeler le serveur et faire du pain, puis ouvrez un modal". Vous pourrez facilement accéder simplement au service lui-même sans avoir à ajouter ou à modifier le code HTML et / ou le code de la méthode du contrôleur. Si vous n'aviez qu'une seule ligne sur le contrôleur, vous auriez éventuellement besoin d'utiliser un service, pour étendre la fonctionnalité au levage plus lourd que le client demande.

De plus, si vous avez besoin d'un autre bouton 'Supprimer' ailleurs, vous avez maintenant un attribut de directive ('ng-remove-birthday') que vous pouvez facilement affecter à n'importe quel élément de la page. Cela le rend désormais modulaire et réutilisable. Cela vous sera utile lorsque vous aurez affaire au paradigme des composants Web HEAVY d'Angular 2.0. Il n'y a pas de contrôleur en 2.0. :)

Bon développement !!!



0

si vous avez un ID ou un champ spécifique dans votre article, vous pouvez utiliser filter (). son acte comme Where ().

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

dans le contrôleur:

$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 

du contrôleur (la fonction peut être dans le même contrôleur mais préfère la garder dans un service)

    function removeInfo(id) {
    let item = bdays.filter(function(item) {
      return bdays.id=== id;
    })[0];
    let index = bdays.indexOf(item);
    data.device.splice(indexOfTabDetails, 1);
  }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.