【问题标题】:Remove items from Array skips certain items从数组中删除项目会跳过某些项目
【发布时间】:2016-07-11 17:10:56
【问题描述】:

我有以下页面(简单):

如您所见,在顶部我有一个输入,然后是<ul>,最后是一个保存更改的按钮。我的<ul> 绑定到items 的数组。一旦用户点击 Uloz zmeny(保存更改),我将触发 ng-click="vm.SaveChanges()",如下所示:

    vm.SaveChanges = function () {
        angular.forEach(vm.items, function (value, key) {

            if (value.toRemove == true) {
                //remove item from the list

                var iIndex = vm.items.indexOf(value);
                vm.items.splice(iIndex, 1);
            };
        });
    };

vm 在我的代码开头定义如下:

(function () {
    "use strict";

    angular.module("app-shopping").controller("itemsController", itemsController);

    function itemsController($http) {
        var vm = this;

        vm.items = [];.....more code after here

我的''下的每个项目都有以下结构:

  {
    "id": 2,
    "orderId": 2,
    "text": "Item 2",
    "toRemove": true
  },

最后,当用户检查<li> 下的项目时,我触发了vm.toggleCompleted(),它看起来像这样(它只是将当前项目的布尔状态从真更改为假,反之亦然):

    vm.toggleCompleted = function (sItem) {
        sItem.toRemove = !sItem.toRemove;
    };

问题来了:为什么当我运行这段代码时,它没有删除数组中的所有选中项?例如,在这种特定情况下(见上图),它只会删除Item 2 并跳过Item 3。我相信这个问题是由于当Item 2 从列表中删除时,Item 3 采用已经存在的Item 2 的索引,因此被跳过。这个假设正确吗?如果是,我需要如何更改代码才能使其运行?

附:按照建议编辑我的代码:

        <li class="list-group-item" ng-repeat="sItem in vm.items">
            <div class="checkbox checkbox-success">
                <input id="ListItem{{$index}}" type="checkbox" placeholder="test placeholder" ng-model="sItem.toRemove" ng-click="sItem.toRemove=!sItem.toRemove" />
                <label for="ListItem{{$index}}">{{sItem.text}}</label>
            </div>
        </li>

【问题讨论】:

  • 你能创建一个 plunker 吗?
  • 我认为你的假设是正确的。删除所有项目的一个聪明方法是反向循环 - 从最高索引开始并从那里删除。

标签: javascript jquery arrays angularjs


【解决方案1】:

我已按以下方式更改了代码,现在可以正常工作了:

    vm.SaveChanges = function () {
        for (var i = vm.items.length - 1; i > -1; i--)
        {
            if (vm.items[i].toRemove == true)
            {
                vm.items.splice(i, 1);
            }
        }
    };

【讨论】:

【解决方案2】:

在复选框输入的地方使用下面的toggleCompleted代替

<input type="checkbox" ng-model="item.toRemove" ng-click="item.toRemove=!item.toRemove" />

并使用您的新 saveChanges 方法..这应该可以正常工作..

【讨论】:

  • 这看起来棒极了!我更改了代码,但我无法再检查该项目(始终未选中)。我已将代码添加到我的帖子中
  • 您是否浏览过我在评论中粘贴的 plunk .. 再说一遍 ..plnkr.co/edit/6tpG8Kr4vWyRlF5ZNtxs?p=preview 。 …
  • 我创建了一个 plunk,但由于未知原因,它不起作用。无论如何,完整的代码在这里:plnkr.co/edit/vfWZmHLJ3oRxiMLuh5H9
  • 其实你的ng-app 不是plunker,就是这样。你也没有包含 ngRoute 库。
  • 发生这种情况是因为新的范围生成 .. 浏览了几篇范围相关的文章,然后你会自动开始理解这些东西 .. 一篇我发现有用的 github.com/angular/angular.js/wiki/理解范围
【解决方案3】:

是的,要绕过这个问题,只需恢复数组遍历,因为这样可以保证在删除过程中未检查元素的位置不会发生变化。

【讨论】:

    【解决方案4】:

    所以,你最后的代码应该是这样的:

    模板:

    <li class="list-group-item" ng-repeat="sItem in vm.items">
        <div class="checkbox checkbox-success">
            <input id="ListItem{{$index}}" type="checkbox" placeholder="test placeholder" ng-click="sItem.toRemove = !sItem.toRemove" />
            <label for="ListItem{{$index}}">{{sItem.text}}</label>
        </div>
    </li>
    
    
    <button class="btn btn-success" ng-click="SaveChanges()"> Save</button>
    

    控制器:

    $scope.SaveChanges = function () {
    
            for (var i = $scope.vm.items.length - 1; i > -1; i--){
                if ($scope.vm.items[i].toRemove) {
                    $scope.vm.items.splice(i, 1);
                };
            }
    }
    

    【讨论】:

    • 嗨,Yoan,谢谢您的回答。但是有一个问题 - 为什么要在您已经知道某个项目的索引时尝试检索它 - 变量 i 是实际索引。这对我没有任何意义
    猜你喜欢
    • 2012-05-30
    • 2021-10-19
    • 2018-09-04
    • 2019-08-05
    • 2021-10-03
    • 1970-01-01
    相关资源
    最近更新 更多