Comment supprimer un élément d'un tableau dans la portée AngularJS?

153

Liste de tâches simple, mais avec un bouton de suppression sur la page de liste pour chaque élément:

entrez la description de l'image ici

HTML du modèle pertinent:

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

Méthode de contrôleur pertinente:

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

J'ai essayé $scope.persons.pull(person)et $scope.persons.remove(person).

Bien que la base de données ait été supprimée avec succès, je ne peux pas extraire cet élément de la portée et je ne veux pas faire un appel de méthode au serveur pour les données que le client possède déjà, je veux simplement supprimer cette personne de la portée.

Des idées?

Au revoir
la source
J'exécute cette route whit $, et la vue ne fonctionnera pas correctement. J'ai toujours eu une page vide après avoir fait la suppression :-(
zx1986
Ont écrit un article similaire codepedia.info/angularjs-delete-table-row-tr-on-click
Satinder singh
il ne s'agit pas tellement de supprimer de la portée mais plutôt d'un tableau, et ce serait la même chose quel que soit l'angle, c'est juste du javascript
Xsmael

Réponses:

259

Votre problème ne concerne pas vraiment Angular, mais les méthodes Array. La méthode appropriée pour supprimer un élément particulier d'un tableau est d'utiliser Array.splice. De plus, lorsque vous utilisez ng-repeat, vous avez accès à la fonction spéciale$index propriété , qui est l'index actuel du tableau que vous avez passé.

La solution est en fait assez simple:

Vue:

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

Manette:

$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);
  });
};
Josh David Miller
la source
1
@ScottMalachowski Vous avez raison. J'ai oublié cette partie. J'ai révisé ma réponse pour refléter cela, donc elle sera cohérente avec la vôtre.
Josh David Miller
13
Attention - cette solution basée sur un index ne fonctionnera pas si vous utilisez plusieurs ng-répétitions du même objet dans une vue (par exemple, Tâches planifiées, Tâches non planifiées, Tâches terminées, toutes issues de $ scope.tasks) car vous aurez plusieurs éléments avec index 2, 3, 4, etc.
shacker
Le commentaire ci-dessus, de @shacker, à propos de plusieurs ng-répétitions avec différents ensembles filtrés du même tableau, est juste. Utilisez la méthode ci-dessous avec indexOf
Andrew Kuklewicz
4
@AndrewKuklewicz - indexOfpeut être une opération plus coûteuse; sans filtrage, c'est totalement inutile. Mais avec le filtrage, ce indexOfserait la méthode appropriée.
Josh David Miller
J'ai du mal avec cela et j'ai dû apporter une modification mineure à la génération de balises ci-dessus - being - delete ({{$ index}}) avec le {{}} sinon j'ai la chaîne $ index - MAIS j'ai quelque chose qui ne va pas parce qu'il n'appelle jamais cette méthode. C'est le cas lorsque je supprime toute mention de l'index comme delete () mais cela n'aide pas vraiment.
mikemil
310

Vous devrez trouver l'index du persondans votre personstableau, puis utiliser la spliceméthode du tableau :

$scope.persons.splice( $scope.persons.indexOf(person), 1 );
Joseph Silber
la source
49
c'est une meilleure réponse; fonctionne lorsque la liste a été filtrée de sorte que cet index dans la vue ne soit pas le même que dans le tableau de la portée.
Andrew Kuklewicz le
5
C'est en effet la meilleure réponse. Notez qu'en plus du cas d'utilisation des listes filtrées mentionné par Andrew, cette approche couvre également le cas dans lequel vous supprimez plusieurs personnes et les demandes Ajax pour ces suppressions sont dans le désordre. Si vous avez utilisé les index de lignes avant le retour d'appel Ajax, vous finirez par supprimer les mauvaises lignes.
Joris
4
C'est mieux dans certains cas, mais avec indexOf vous devez parcourir tous les éléments pour trouver le bon, dans la réponse Josh, vous obtenez l'index et l'élément plus rapidement
daver
@mike - Utilisez ce polyfill .
Joseph Silber
8

J'utiliserais la bibliothèque Underscore.js qui contient une liste de fonctions utiles.

without

without_.without(array, *values)

Renvoie une copie du tableau avec toutes les instances des valeurs supprimées.

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

Exemple

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

Voir Démo dans JSFiddle .


filter

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

// => [2, 4, 6]

Exemple

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

Voir Démo dans Fiddle .

Maxime Shoustin
la source
J'utiliserais probablement $scope.nodes = _.without($scope.nodes, node);parce qu'il fait référence aunode
jake
Sur les navigateurs modernes, vous pouvez utiliser Array.prototype.filter. _.filter(array, fun)devient array.filter(fun).
bfontaine
7
$scope.removeItem = function() {
    $scope.items.splice($scope.toRemove, 1);
    $scope.toRemove = null;
};

cela fonctionne pour moi!

cebor
la source
4

Si vous avez une fonction associée à la liste, lorsque vous créez la fonction d'épissure, l'association est également supprimée. Ma solution:

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

Le paramètre de liste est nommé items . Le paramètre x.done indique si l'élément sera supprimé.

Autres références: un autre exemple

J'espère vous aider. Salutations.

Drako
la source
2

Pour la réponse acceptée de @Joseph Silber ne fonctionne pas, car indexOf renvoie -1. Ceci est probablement dû au fait qu'Angular ajoute une clé de hachage, ce qui est différent pour mon $ scope.items [0] et mon élément. J'ai essayé de résoudre cela avec la fonction angular.toJson (), mais cela n'a pas fonctionné :(

Ah, j'ai découvert la raison ... J'utilise une méthode chunk pour créer deux colonnes dans ma table en regardant mon $ scope.items. Désolé!

gabn88
la source
2

Vous pouvez également utiliser ceci

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

Angular a une fonction intégrée appelée arrayRemove, dans votre cas, la méthode peut simplement être:

arrayRemove($scope.persons, person)
Allen
la source
1
array.splice(array.pop(item));
Taran
la source
0

Pour supprimer un élément de la portée, utilisez:

// remove an item
    $scope.remove = function(index) {
        $scope.items.splice(index, 1);
    };

De entrez la description du lien ici

Cubiczx
la source