如何从angular.js数组中删除元素/节点


71

我试图从数组中删除元素,$scope.items以便在视图中删除项目ng-repeat="item in items"

仅出于说明目的,下面是一些代码:

for(i=0;i<$scope.items.length;i++){
    if($scope.items[i].name == 'ted'){
      $scope.items.shift();
    }
}

如果名称正确,我想从视图中删除第一个元素吗?它工作正常,但是视图会重新加载所有元素。因为所有阵列键都已移动。这在我正在创建的移动应用程序中造成了不必要的延迟。

有人对此问题有解决方案吗?


我已经成功使用splice修改了ng-repeat中使用的数组,并且没有怪异的副作用。
BoxerBucks

看起来项目是一个数组数组,或者您不能调用items [i] .shift();
zs2020

嗨,谢谢您的答复。抱歉,我的问题代码中有错别字,我刚刚更新了它。
TheNickyYo

那么,为什么要从数组而不是位置i的元素中删除第一个元素呢?
zs2020

3行会解决您的问题,只需在控制器中添加$ filter
Maxim Shoustin

Answers:


135

从数组中删除项目没有火箭科学。从任何数组中删除的项目,你需要使用splice$scope.items.splice(index, 1);这是一个例子

的HTML

<!DOCTYPE html>
<html data-ng-app="demo">
  <head>
    <script data-require="angular.js@1.1.5" data-semver="1.1.5" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>
  <body>
    <div data-ng-controller="DemoController">
      <ul>
        <li data-ng-repeat="item in items">
          {{item}}
          <button data-ng-click="removeItem($index)">Remove</button>
        </li>
      </ul>
      <input data-ng-model="newItem"><button data-ng-click="addItem(newItem)">Add</button>
    </div>
  </body>
</html>

的JavaScript

"use strict";

var demo = angular.module("demo", []);

function DemoController($scope){
  $scope.items = [
    "potatoes",
    "tomatoes",
    "flour",
    "sugar",
    "salt"
  ];

  $scope.addItem = function(item){
    $scope.items.push(item);
    $scope.newItem = null;
  }

  $scope.removeItem = function(index){
    $scope.items.splice(index, 1);
  }
}

(index,1)
ShibinRagh


24
注意$index不一定与$scope.items索引匹配。特别是如果您使用orderByfilter。我认为使用$index是不可扩展的,可能会很危险。
Antoine Pinsard

@AntoinePinsard您推荐什么呢?
stackPusher

1
@stackPusher,如果我没记错的话,我使用了bpaul的解决方案stackoverflow.com/a/22160628/1529346
Antoine Pinsard

123

对于任何回到这个问题的人。正确的“角度方式”是使用$ filter从数组中删除项目。只需将$ filter注入控制器,然后执行以下操作:

$scope.items = $filter('filter')($scope.items, {name: '!ted'})

您无需加载任何其他库或使用Javascript原语。


如果您有一个名称为“ ted”和“ teddy”的元素,并且只想删除“ ted”元素,是否可以使用?
Jervelund 2014年

2
@Jervelund是的,您可以在最后使用true :,$filter('filter')($scope.items, {name: '!ted'}, true)请参阅docs.angularjs.org/api/ng/filter/filter
Betty St

4
我认为这个答案应该是公认的,因为它具有棱角感。
MrBoJangles

是否可以使用过滤器删除包含特定数字ID的元素?$filter('filter')($scope.items, {id: 42}, true);用于查找元素,但是我还没有找到否定它的方法,{id: "!42"}因为它是字符串,所以不起作用。
奥斯卡

29
该作品: $filter('filter')($scope.items, function(value, index) {return value.id !== 42;});
奥斯卡


11

因为当您shift()对数组进行操作时,它会更改数组的长度。因此,for循环将陷入混乱。您可以从头到尾循环以避免出现此问题。

顺便说一句,我假设您尝试删除位置i处的元素,而不是数组的第一个元素。($scope.items.shift();在您的代码中将删除数组的第一个元素)

for(var i = $scope.items.length - 1; i >= 0; i--){
    if($scope.items[i].name == 'ted'){
        $scope.items.splice(i,1);
    }
}

8

这是可能会对您filterUnderscore library帮助的地方,我们将删除名称为“ ted”的商品

$scope.items = _.filter($scope.items, function(item) {
    return !(item.name == 'ted');
 });

2
这就是“成角度”的方式!当然可以改善:$scope.items = $filter('filter').filter($scope.items, {name: '!ted'})
bpaul 2014年

3
@bpaul的改进不错,但看起来有错误,应该是:$scope.items = $filter('filter')($scope.items, {name: '!ted'})
Eugene

1
@Eugene一点也不。我使用了Underscore库,添加了链接。
Maxim Shoustin 2014年

谢谢@Eugene,这是一个错字。发布之前,我应该先测试代码!另外,这应该是一个答案,因为它不需要下划线(或任何其他lib)并且是惯用的。我将其添加。
bpaul 2014年

6

只是对“角度”解决方案稍作扩展。我想根据数字ID排除项目,因此!方法行不通。适用于{name:'ted'}或{id:42}的更通用的解决方案是:

mycollection = $filter('filter')(myCollection, { id: theId }, function (obj, test) { 
                                                             return obj !== test; });

5

我喜欢@madhead提供的解决方案

但是我遇到的问题是它不适用于排序列表,因此我没有传递索引到delete函数,而是传递了项,然后通过indexof获得了索引

例如:

var index = $scope.items.indexOf(item);
$scope.items.splice(index, 1);

madheads示例的更新版本如下: 链接到示例

的HTML

<!DOCTYPE html>
<html data-ng-app="demo">
  <head>
    <script data-require="angular.js@1.1.5" data-semver="1.1.5" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>
  <body>
    <div data-ng-controller="DemoController">
      <ul>
        <li data-ng-repeat="item in items|orderBy:'toString()'">
          {{item}}
          <button data-ng-click="removeItem(item)">Remove</button>
        </li>
      </ul>
      <input data-ng-model="newItem"><button data-ng-click="addItem(newItem)">Add</button>
    </div>
  </body>
</html>

的JavaScript

"use strict";

var demo = angular.module("demo", []);

function DemoController($scope){
  $scope.items = [
    "potatoes",
    "tomatoes",
    "flour",
    "sugar",
    "salt"
  ];

  $scope.addItem = function(item){
    $scope.items.push(item);
    $scope.newItem = null;
  }

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

3

我对此的解决方案(尚未引起任何性能问题):

  1. 使用remove方法扩展数组对象(我敢肯定您将需要多次):
Array.prototype.remove = function(from, to) {
  var rest = this.slice((to || from) + 1 || this.length);
  this.length = from < 0 ? this.length + from : from;
  return this.push.apply(this, rest);
};

我在我所有的项目中都使用了它,并且鸣谢到John Resig John Resig的站点

  1. 使用forEach和基本检查:
$scope.items.forEach(function(element, index, array){
          if(element.name === 'ted'){
              $scope.items.remove(index);
          }
        });

最后,$ digest将在angularjs中触发,并且我的UI立即更新,没有任何可识别的延迟。


在遍历列表时删除元素真的安全吗?
Volte 2015年

通常,您应该谨慎执行此操作。我要说的使用.forEach,而不是一个for循环使得它的安全作为MDN developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...说:“forEach()这样执行提供的回调一次,每个元素存在在数组中按升序排列。对于已删除或未初始化的索引属性(即在稀疏数组上),不会调用它。” 因此,在访问之后/之前或访问之前删除的项目只是被“忽略”了,恕我直言,这对于这种情况是安全的。
Fer To

1

如果您有与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指示是否将删除该项目。希望对你有帮助。问候。


1

使用indexOf函数并不能减少我的REST资源集合。

我必须创建一个函数来检索位于资源集合中的资源的数组索引:

factory.getResourceIndex = function(resources, resource) {
  var index = -1;
  for (var i = 0; i < resources.length; i++) {
    if (resources[i].id == resource.id) {
      index = i;
    }
  }
  return index;
}

$scope.unassignedTeams.splice(CommonService.getResourceIndex($scope.unassignedTeams, data), 1);

1

我的解决方案很简单

app.controller('TaskController', function($scope) {
 $scope.items = tasks;

    $scope.addTask = function(task) {
        task.created = Date.now();
        $scope.items.push(task);
        console.log($scope.items);
    };

    $scope.removeItem = function(item) {
        // item is the index value which is obtained using $index in ng-repeat
        $scope.items.splice(item, 1);
    }
});

0

我的商品具有唯一的ID。我通过用angulars$filter服务过滤模型来删除一个:

var myModel = [{id:12345, ...},{},{},...,{}];
...
// working within the item
function doSthWithItem(item){
... 
  myModel = $filter('filter')(myModel, function(value, index) 
    {return value.id !== item.id;}
  );
}

作为id,您还可以使用模型项的$$ hashKey属性: $$hashKey:"object:91"

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.