如何使用ng-click从数组中删除项目或对象?


261

我正在尝试编写一个函数,该函数使我可以在单击按钮时删除项目,但我认为我对该函数感到困惑-我可以使用$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-click而已在摘要循环中)。您是否要从数组中删除项目?
Mark Rajcok

@MarkRajcok :)是的,这就是我正在尝试做的事情
Jess McKenzie

remove()ng-click您拥有的方式没有上下文。在标记中需要更多详细信息,以显示要删除的内容以及该内容是否在ng-repeat其中,或者要删除的内容来自何处,或者您想要什么行为remove()
charlietfl 2013年

@charlietfl,它在ng-repeat之内我已经更新了问题
Jess McKenzie

这是我的第一篇文章,其中介绍了如何使用ng-repeat codepedia.info/angularjs-delete-table-row-tr-on-click
Satinder singh

Answers:


551

要删除项目,您需要将其从数组中删除,并且可以将bday项目传递给标记中的remove函数。然后在控制器中查找项目的索引并从数组中删除

<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

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

编辑:如果使用服务器进行实时更新将使用您创建的服务 $resource来管理阵列更新,同时更新服务器


62
$index如果您的列表是按模板过滤的,则直接使用可能会产生错误。这是一个模板。ng-click='remove(bday)'然后使用会更安全arr.splice(arr.indexOf(bday),1);
UmurKontacı2013年

6
您不需要传递$ index,因为您可以在方法内部使用“ this”。$ scope.remove = function(){$ scope.bdays.splice(this。$ index,1); }
matchdav

1
@matthewdavidson this is undefined。可能是Plunker / jsfiddle?
Tjorriemorrie

11
.indexOf(item)如果未找到,将返回-1,这可能会导致删除数组末尾的项目。
本·王尔德2014年


54

这是正确的答案:

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

在@charlietfl的答案中。我认为这是错误的,因为您通过$index了参数传递,但是在控制器中使用了愿望。如我错了请纠正我 :)


看起来这两个答案是等效的,尽管您的函数可以接受不带$的索引,并且仍然可以使用。
svarog 2014年

这应该是正确的答案。 indexOf仅适用于IE9 +版本
levi 2015年

17
如果您在ng-repeat中有orderBy或过滤器,则此方法将无效
Joan-Diego Rodriguez

如果您使用$ index跟踪,效果会更好
Ankit Balyan 2015年

@ Joan-DiegoRodriguez如果您有过滤器/ orderby,如何使它工作?别介意读XMLilley的答案
jamesmstone

26

如果您在ng-repeat中

您可以使用一个班轮选项

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

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

$index 由angular用来显示内部数组的当前索引 ng-repeat


1
我喜欢并使用了这种衬板
etoricky

24

$index在基本情况下,使用效果很好,并且@charlietfl的答案很好。但是有时候,$index这还不够。

假设您有一个数组,以两个不同的ng-repeat呈现。这些ng-repeat的其中一个针对具有true属性的对象进行过滤,而另一个针对falsy属性进行过滤。呈现了两个不同的过滤后的数组,它们是从单个原始数组派生的。(或者,如果它有助于想象:也许你的人一个数组,你想一个NG重复该数组中的妇女,另一个用于在男子相同的阵列。)你的目标:从可靠地删除原始数组,使用来自已过滤数组成员的信息。

在每个过滤后的数组中,$ index都不是原始数组中该项的索引。这将是过滤后的子数组中的索引。因此,您将无法在原始people数组中分辨出该人的索引,而只能从womenmen子数组中知道$ index 。尝试使用它进行删除,除了需要的地方之外,其他地方都会有项目消失。该怎么办?

如果您很幸运地使用了一个数据模型,该数据模型包含每个对象的唯一标识符,则可以使用该模型而不是$ index来找到该对象并将splice其从主数组中移出。(使用下面的示例,但带有唯一的标识符。)但是,如果您不是很幸运的话?

Angular实际上通过称为的唯一属性来增强ng重复数组(在主数组中,是原始数组中)中的每个项目$$hashKey。您可以在原始数组中搜索$$hashKey要删除的项目的匹配项,然后以这种方式删除它。

请注意,这$$hashKey是一个实现细节,未包含在已发布的ng-repeat API中。他们可以随时删除对该财产的支持。但是可能不会。:-)

$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's 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)"

编辑:使用类似这样的函数,该函数将键入$$hashKey而不是特定于模型的属性名称,而不是特定于模型的属性名称,也具有使该函数可在不同模型和上下文之间重用的显着附加优势。为它提供数组引用和项引用,它应该可以正常工作。


10

我通常是这样写的:

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


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

希望这对您有帮助。您必须在$ scope和[yourArray]之间使用点(。)。


(index,1)中的“ 1”是什么意思
ShibinRagh

@ShibinRagh是的deleteCount一个整数,指示要删除的旧数组元素的数量。如果deleteCount为0,则不会删除任何元素。在这种情况下,您应该至少指定一个新元素。如果deleteCount大于开始时数组中剩余的元素数,则将删除数组末尾的所有元素。 Array.prototype.splice()文档
ᴍᴀᴛᴛʙᴀᴋᴇʀ

9

在已接受的答案的基础上,它将与一起使用ngRepeatfilter并更好地处理期望:

控制器:

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

视图:

ng-click="vm.remove(item,$scope.bdays)"

您没有在控制器中分配“删除”到$ scope.vm,因此此代码不起作用。现在,如果您执行此操作... $ scope.vm = {删除:function(){...}},那么它将完成。
贾斯汀·鲁索

4

没有控制器的实现。

<!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 track by $index">{{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)

index:必填。一个整数,指定要添加/删除项目的位置,请使用负值指定从数组末尾开始的位置。

howmanyitem(s):可选。要删除的项目数。如果设置为0,则不会删除任何项目。

item_1,...,item_n:可选。要添加到数组中的新项目


1
这是正确的答案。为什么要依靠控制器执行简单的JavaScript调用?
Elle Fie '18

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”),您可以轻松地将其分配给页面上的任何元素。现在,这使其成为模块化且可重复使用的。在处理Angular 2.0的HEAVY Web组件范例时,这将派上用场。2.0中没有控制器。:)

快乐发展!!!



0

如果项目中有ID或任何特定字段,则可以使用filter()。它的行为就像Where()。

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

在控制器中:

$scope.remove = function(item) { 
  $scope.bdays = $scope.bdays.filter(function (element) {
                    return element.ID!=item.ID
                });
}

0
Pass the id that you want to remove from the array to the given function 

来自控制器(功能可以在同一控制器中,但更喜欢将其保留在服务中)

    function removeInfo(id) {
    let item = bdays.filter(function(item) {
      return bdays.id=== id;
    })[0];
    let index = bdays.indexOf(item);
    data.device.splice(indexOfTabDetails, 1);
  }
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.