Як видалити елемент з масиву в області AngularJS?


153

Простий список справ, але з кнопкою видалення на сторінці списку для кожного елемента:

введіть тут опис зображення

Відповідний HTML шаблону:

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

Відповідний метод контролера:

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

Я спробував $scope.persons.pull(person)і $scope.persons.remove(person).

Хоча база даних успішно видалена, я не можу витягнути цей елемент із сфери застосування, і я не хочу здійснювати виклик методу на сервер для даних, які клієнт вже має, я просто хочу видалити цю людину з області дії.

Будь-які ідеї?


Я проводжу цей маршрут $ whit, і представлення не буде добре працювати. Після видалення я завжди отримував порожню сторінку :-(
zx1986


мова йде не стільки про те, щоб видалити з області, а скоріше з масиву, і це було б те саме, незалежно від кутового, його справедливий javascript
Xsmael

Відповіді:


259

Ваша проблема насправді не з кутовим, а з методами Array. Правильний спосіб видалити конкретний елемент із масиву - це Array.splice. Також при використанні ng-повтору ви маєте доступ до спеціального $indexвластивості, що є поточним індексом масиву, який ви передали.

Рішення насправді досить просте:

Вид:

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

Контролер:

$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 Ви маєте рацію. Я забув цю частину. Я переглянув свою відповідь, щоб це відобразити, тому вона буде відповідати вашій.
Джош Девід Міллер

13
Обережно - це рішення, засноване на індексах, не працюватиме, якщо ви використовуєте декілька ng-повторень одного і того ж об’єкта в перегляді (наприклад, Заплановані завдання, Незаплановані завдання, Виконані завдання, які виходять із $ range.tasks), оскільки у вас буде кілька елементів з індекс 2, 3, 4 тощо
шейкер

Коментар вище, від @shacker, про кілька повторень ng з різними відфільтрованими наборами одного і того ж масиву, прямо зараз. Використовуйте метод нижче із indexOf
Андрій Куклевич

4
@AndrewKuklewicz - indexOfможе бути більш дорогою операцією; без фільтрування це зовсім непотрібно. Але з фільтруванням indexOfбув би відповідний метод.
Джош Девід Міллер

Я боюся з цим, і мені довелося внести незначну зміну в покоління тегів вище - being - delete ({{$ index}}) з {{}} в іншому випадку я отримав рядок $ index - Але я щось не так, оскільки це ніколи не називає цей метод. Це відбувається, коли я видаляю будь-яку згадку про індекс, як delete (), але це насправді не допомагає.
mikemil

310

Вам доведеться знайти індекс personв своєму personsмасиві, а потім скористатися spliceметодом масиву :

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

49
це краща відповідь; працює, коли список було відфільтровано так, що індекс у представленні не такий, як у масиві за обсягом.
Андрій Куклевич

5
Це справді краща відповідь. Зауважте, що крім відфільтрованих списків використовується випадок, згаданий Ендрю, цей підхід охоплює також випадок, коли ви видаляєте кілька осіб, а запити Ajax для цих видалених повертаються з ладу. Якщо ви використовували індекси рядків до повернення виклику Ajax, ви видалите неправильні рядки.
Йоріс

4
У деяких випадках краще, але з indexOf вам доведеться переглядати всі елементи, щоб знайти потрібний, у відповіді Джоша ви отримуєте індекс та пункт швидше
daver

@mike - використовуйте цю поліфункцію .
Джозеф Сільбер

8

Я використовував би бібліотеку Underscore.js, яка містить список корисних функцій.

without

without_.without(array, *values)

Повертає копію масиву зі всіма видаленими екземплярами значень.

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

Приклад

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

Дивіться демо в JSFiddle .


filter

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

// => [2, 4, 6]

Приклад

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

Дивіться демонстрацію у Фідділі .


Я, мабуть, використовую, $scope.nodes = _.without($scope.nodes, node);тому що він посилається наnode
Джейк

У сучасних браузерах можна використовувати Array.prototype.filter. _.filter(array, fun)стає array.filter(fun).
bfontaine

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

це працює для мене!


4

Якщо у вас є якась функція, пов’язана зі списком, під час створення функції зрощення, асоціація також видаляється. Моє рішення:

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

Параметр списку називається предметами . Параметр x.done вказує, чи буде елемент видалено.

Інші посилання: Ще один приклад

Сподіваюся, вам допоможуть. Привітання.


2

Для прийнятої відповіді @Joseph Silber не працює, тому що indexOf повертає -1. Це, мабуть, тому, що Angular додає хешкей, який відрізняється від мого $ range.items [0] та мого елемента. Я намагався вирішити це за допомогою функції angular.toJson (), але це не вийшло :(

Ах, я з'ясував причину ... Я використовую метод блоку, щоб створити два стовпчики в моїй таблиці, спостерігаючи за моїми $ range.items. Вибачте!


2

Ви також можете використовувати це

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

1

У кутових є вбудована функція, яка називається arrayRemove, у вашому випадку метод може бути просто:

arrayRemove($scope.persons, person)


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.