如何从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)

尽管数据库已成功删除,但是我无法从范围中删除该项目,也不想对服务器进行方法调用以获取客户端已经拥有的数据,我只想从范围中删除此人。

有任何想法吗?


我运行这个$ route的视图,该视图将无法正常工作。在执行删除操作后,我总是得到一个空白页:-(
zx1986


这不是从作用域中删除而是从数组中删除,与角度删除无关,它只是javascript
而已

Answers:


259

您的问题不是Angular,而是Array方法。从数组中删除特定项目的正确方法是使用Array.splice。另外,使用ng-repeat时,您可以访问特殊$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重复(例如,计划任务,计划外任务,已完成任务全部来自$ scope.tasks),则此基于索引的解决方案将无法工作,因为您将拥有多个索引2,3,4,等等
shacker

上面@shacker发表的评论是关于多个ng-repeats,它们具有相同数组的不同过滤集。在indexOf中使用下面的方法
Andrew Kuklewicz 2013年

4
@AndrewKuklewicz- indexOf操作可能更昂贵;无需过滤,则完全没有必要。但是使用过滤indexOf将是适当的方法。
Josh David Miller

我为此感到吃力,并且不得不对上面的标记生成进行较小的更改-用{{}}-delete({{{$ index}})否则,我会得到字符串$ index-但是我出错了,因为它永远不要调用该方法。当我删除索引的任何提及(例如delete())时,它确实起作用,但这并没有真正的帮助。
mikemil

310

您必须personpersons数组中找到的索引,然后使用数组的splice方法:

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

49
这是一个更好的答案;当列表已被过滤,以便视图中的索引与作用域中的数组中的索引不同时,此函数起作用。
Andrew Kuklewicz

5
这确实是更好的答案。请注意,除了安德鲁提到的过滤列表用例之外,该方法还涵盖了删除多个人员并且针对这些删除的Ajax请求无序返回的情况。如果您使用了Ajax调用返回之前的行索引,则最终将删除错误的行。
2014年

4
在某些情况下会更好,但是使用indexOf时,您必须遍历所有项目以找到正确的项目,在Josh答案中,您会更快地获得索引和项目
daver 2014年

@mike-使用 polyfill 。
约瑟夫·西尔伯

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中的 Demo 。


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
jake

在现代浏览器上,您可以使用Array.prototype.filter_.filter(array, fun)成为array.filter(fun)
bfontaine 2014年

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

这对我有用!


4

如果您有与list相关联的任何功能,则在执行拼接功能时,该关联也将被删除。我的解决方案:

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

列表参数被命名为items。参数x.done指示是否将删除该项目。

另一个参考:另一个例子

希望对你有帮助。问候。


2

对于@Joseph Silber的可接受答案无效,因为indexOf返回-1。这可能是因为Angular添加了一个hashkey,这对于我的$ scope.items [0]和我的商品是不同的。我试图用angular.toJson()函数解决这个问题,但是它没有用:(

啊,我找到了原因...我使用块方法通过查看$ scope.items在表中创建两列。抱歉!


2

你也可以用这个

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

1

Angular有一个称为的内置函数arrayRemove,在您的情况下,方法可以简单地是:

arrayRemove($scope.persons, person)


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.