【问题标题】:How to remove elements/nodes from angular.js array如何从 angular.js 数组中删除元素/节点
【发布时间】:2013-08-20 14:45:12
【问题描述】:

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

这里只是为了演示目的,这里有一些代码:

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

如果有名称 ted,我想从视图中删除第一个元素,对吗?它工作正常,但视图重新加载所有元素。因为所有的数组键都发生了变化。这在我正在创建的移动应用程序中造成了不必要的延迟..

谁有解决这个问题的办法?

【问题讨论】:

  • 我已经成功使用 splice 修改了一个用于 ng-repeat 的数组,没有奇怪的副作用。
  • 看起来items是array的array,或者不能调用items[i].shift();
  • 您好,感谢您的回复。抱歉,我的问题代码中有错别字,我刚刚更新了它。
  • 那为什么要从数组中删除第一个元素而不是i位置的元素呢?
  • 3行就能解决你的问题,只需在控制器中添加$filter

标签: angularjs scope angularjs-ng-repeat


【解决方案1】:

从数组中删除项目没有火箭科学。要从任何数组中删除项目,您需要使用splice:$scope.items.splice(index, 1);Here is an example:

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

【讨论】:

【解决方案2】:

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

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

您不需要加载任何额外的库或诉诸 Javascript 原语。

【讨论】:

  • 如果您有一个名为“ted”和“teddy”的元素,并且只想删除“ted”元素,这是否可行?
  • @Jervelund 是的,您可以在最后使用 true :$filter('filter')($scope.items, {name: '!ted'}, true) ,请参阅docs.angularjs.org/api/ng/filter/filter
  • 我认为这个答案应该是被接受的,因为它有角度。
  • 是否可以使用过滤器删除包含特定数字 id 的元素? $filter('filter')($scope.items, {id: 42}, true); 用于查找元素,但我还没有找到否定它的方法,{id: "!42"} 不起作用,因为它是一个字符串。
  • 这工作:$filter('filter')($scope.items, function(value, index) {return value.id !== 42;});
【解决方案3】:

您可以使用纯 javascript - Array.prototype.filter()

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

【讨论】:

    【解决方案4】:

    因为当你对数组执行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);
        }
    }
    

    【讨论】:

      【解决方案5】:

      这里是 filterUnderscore library 可能会对您有所帮助,我们删除名称为“ted”的项目

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

      【讨论】:

      • 这是“角度”的方式!当然可以改进:$scope.items = $filter('filter').filter($scope.items, {name: '!ted'})
      • @bpaul 的改进不错,但看起来有错误,应该是:$scope.items = $filter('filter')($scope.items, {name: '!ted'})
      • @Eugene 一点也不。我使用了下划线库,添加了链接。
      • 谢谢@Eugene,这是一个错字。我应该在发布之前测试代码!此外,这应该是一个答案,因为它不需要下划线(或任何其他库)并且是惯用的角度。我会添加它。
      【解决方案6】:

      只是稍微扩展了“角度”解决方案。我想根据它的数字 id 排除一个项目,所以 !方法不起作用。 适用于 { name: 'ted' } 或 { id: 42 } 的更通用的解决方案是:

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

      【讨论】:

        【解决方案7】:

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

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

        例如:

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

        以下是 madheads 示例的更新版本: link to example

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

        【讨论】:

          【解决方案8】:

          我对此的解决方案(没有导致任何性能问题):

          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's Site

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

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

          【讨论】:

          • 在遍历列表时删除元素真的安全吗?
          • 一般来说,你应该小心这样做。我会说使用 .forEach 而不是 for 循环使其安全,因为 MDN developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 说:“forEach() 对数组中存在的每个元素按升序执行一次提供的回调。它不会为具有被删除或未初始化(即在稀疏数组上)。”因此,访问后/访问前删除的项目只是“忽略”,恕我直言,这对于这种情况是安全的。
          【解决方案9】:

          如果你有任何关联到列表的函数,当你创建拼接函数时,关联也会被删除。我的解决方案:

          $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 指示该项目是否将被删除。希望能帮到你。问候。

          【讨论】:

            【解决方案10】:

            使用 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);
            

            【讨论】:

              【解决方案11】:

              我的解决方案非常简单

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

              【讨论】:

                【解决方案12】:

                我的物品有唯一的 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;}
                  );
                }
                

                您也可以使用模型项的 $$hashKey 属性:$$hashKey:"object:91"

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-10-23
                  • 2019-04-09
                  • 2013-09-01
                  • 2020-04-16
                  相关资源
                  最近更新 更多