Как удалить элемент или объект из массива с помощью ng-click?

227

Я пытаюсь написать функцию, которая позволяет мне удалить элемент при нажатии кнопки, но я думаю, что меня путают с функцией - я использую $digest?

HTML и 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
    Вам не нужен $ digest, поскольку он используется для входа в цикл дайджеста Angular (и вы уже находитесь в цикле дайджеста из-за нажатия ng). Вы пытаетесь удалить элемент из массива?
  • 0
    @MarkRajcok :) да, вот что я пытаюсь сделать
Показать ещё 3 комментария
Теги:
edit

9 ответов

497
Лучший ответ

Чтобы удалить элемент, вам нужно удалить его из массива и передать элемент bday в функцию удаления в разметке. Затем в контроллере найдите индекс элемента и удалите из массива

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

Затем в контроллере:

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

Angular автоматически обнаружит изменение в массиве bdays и выполнит обновление ng-repeat

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

РЕДАКТИРОВАТЬ: Если при выполнении живых обновлений с сервером будет использоваться служба, которую вы создаете с помощью $resource, чтобы управлять обновлениями массива одновременно, он обновляет сервер

  • 60
    Использование $index напрямую может привести к ошибкам, если ваш список фильтруется по шаблону. Это шаблонная вещь; безопаснее использовать ng-click='remove(bday)' затем arr.splice(arr.indexOf(bday),1);
  • 0
    @ fastreload хороший улов ... я просто выясняю нюансы углов, посмотрите, что вы имеете в виду сейчас. При фильтрации вы получаете индекс фильтруемого массива, а не исходный массив данных.
Показать ещё 14 комментариев
51

Это правильный ответ:

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

В ответе @charlietfl. Я считаю это неправильным, так как вы передаете $index как параметр, но вместо этого вы используете желание вместо этого в контроллере. Исправьте меня, если я ошибаюсь:)

  • 0
    похоже, что оба ответа эквивалентны, хотя ваша функция может принимать индекс без знака $, и он все равно будет работать.
  • 0
    это должен быть правильный ответ. indexOf ТОЛЬКО работает, если это IE9 +
Показать ещё 6 комментариев
20

, если вы находитесь внутри ng-repeat

вы можете использовать опцию с одним лайнером

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

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

$index используется angular для отображения текущего индекса массива внутри ng-repeat

20

Использование $index отлично работает в основных случаях, а ответ @charlietfl велик. Но иногда, $index недостаточно.

Представьте, что у вас есть один массив, который вы представляете в двух разных ng-repeat. Один из этих ng-repeat фильтруется для объектов, которые имеют правдивое свойство, а другое фильтруется для свойства falsy. Представляются два разных фильтрованных массива, которые выводятся из одного исходного массива. (Или, если это помогает визуализировать: возможно, у вас есть один массив людей, и вы хотите один ng-repeat для женщин в этом массиве, а другой для мужчин в том же массиве.) Ваша цель: надежно удалить из исходный массив, используя информацию от членов фильтрованных массивов.

В каждом из фильтрованных массивов индекс $index не будет индексом элемента в исходном массиве. Это будет индекс в отфильтрованном подматрице. Таким образом, вы не сможете сообщить индексу человека в исходном массиве people, вы будете знать только индекс $из подматрицы women или men. Попытайтесь удалить, используя это, и у вас будут предметы, исчезающие везде, кроме тех, где вы хотели. Что делать?

Если вам посчастливилось использовать модель данных, она содержит уникальный идентификатор для каждого объекта, а затем используйте вместо $index, чтобы найти объект и splice его из основного массива. (Используйте мой пример ниже, но с этим уникальным идентификатором.) Но если вам не повезло?

Angular фактически увеличивает каждый элемент в ng-повторном массиве (в основном, исходном массиве) с уникальным свойством $$hashKey. Вы можете искать исходный массив для соответствия на $$hashKey элемента, который хотите удалить, и избавиться от него таким образом.

Обратите внимание, что $$hashKey - это деталь реализации, не включенная в опубликованный API для ng-repeat. Они могут удалить поддержку этого имущества в любое время. Но, вероятно, нет.: -)

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

Вызов с помощью:

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

EDIT: использование такой функции, что ключи в $$hashKey вместо имени свойства модели также имеют значительное дополнительное преимущество, заключающееся в том, что эту функцию можно использовать повторно для разных моделей и контекстов. Предоставьте ему ссылку на массив и ссылку на ваш объект, и он должен просто работать.

8

Основываясь на принятом ответе, это будет работать с ngRepeat, filter и лучше обработать прогнозы:

Контроллер:

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

Вид:

ng-click="vm.remove(item,$scope.bdays)"
  • 0
    В вашем контроллере вы не присвоили «remove» для $ scope.vm, поэтому этот код не будет работать. Теперь, если вы сделали это ... $ scope.vm = {remove: function () {...}}, тогда это произойдет.
7

Я обычно пишу в таком стиле:

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


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

Надеюсь, это поможет

  • 0
    Что означает «1» в (индекс, 1)
  • 0
    @ShibinRagh Это deleteCount . Целое число, указывающее количество удаляемых старых элементов массива. Если deleteCount равен 0, элементы не удаляются. В этом случае вы должны указать хотя бы один новый элемент. Если deleteCount больше, чем количество элементов, оставшихся в массиве, начиная с начала, то все элементы до конца массива будут удалены. Array.prototype.splice () Документация
3

Я не согласен с тем, что вы должны вызывать метод на вашем контроллере. Вы должны использовать сервис для любых фактических функций, и вы должны определять директивы для любых функций масштабируемости и модульности, а также назначать событие click, которое содержит вызов службы, которую вы вводите в свою директиву.

Так, например, на вашем HTML...

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

Затем создайте директиву...

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

Затем в вашем сервисе...

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

Когда вы правильно пишете свой код, вы легко сможете писать будущие изменения, не переделывая свой код. Он организован правильно, и вы правильно обрабатываете пользовательские события кликов, связывая их с помощью пользовательских директив.

Например, если ваш клиент говорит: "Эй, теперь позвольте заставить его вызвать сервер и сделать хлеб, а затем всплывать модальный". Вы сможете легко просто перейти к самой службе без необходимости добавлять или изменять какой-либо код кода HTML и/или контроллера. Если бы у вас была только одна строка на контроллере, вам в конечном итоге нужно было бы использовать сервис, чтобы расширить функциональность до более тяжелого подъема, который просит клиент.

Кроме того, если вам нужна другая кнопка "Удалить" в другом месте, теперь у вас есть атрибут директивы ( "ng-remove-birthday" ), который вы можете легко назначить любому элементу на странице. Это теперь делает его модульным и многоразовым. Это пригодится при работе с парадигмой веб-компонентов HEAVY Angular 2.0. В 2.0 нет контроллера.:)

Счастливое развитие!!!

0

Без контроллера.

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

Метод splice() добавляет/удаляет элементы в/из массива.

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

индекс: Необходимые. Целое число, указывающее, в какую позицию добавлять/удалять элементы. Используйте отрицательные значения для указания позиции из конца массива.

howmanyitem (s): необязательно. Количество элементов для удаления. Если установлено значение 0, никакие элементы не будут удалены.

item_1,..., item_n: необязательно. Новый элемент (ы), который будет добавлен в массив

  • 0
    Это правильный ответ. Зачем полагаться на контроллер для выполнения простых вызовов JavaScript?
0

Вот еще один ответ. Надеюсь, это поможет.

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

$scope.delete(item){
 var index = this.list.indexOf(item);
                this.list.splice(index, 1);   
}

array.splice(start)
array.splice(start, deleteCount)
array.splice(start, deleteCount, item1, item2, ...)

Полный источник находится здесь
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice

Ещё вопросы

Сообщество Overcoder
Наверх
Меню