AngularJS ngRepeat元素的删除

57

关于如何在ngRepeat指令中实现项目删除,有许多问题。我发现,这可以通过使用ngClick并触发一些删除函数并传递它的索引$index来实现。

然而,我找不到任何一个同时包含多个ngRepeats的示例:

<div ng-controller="MyController">
    <div ng-repeat="email in user.emails">
        {{ email }} <a href>Remove</a>
    </div>

    <div ng-repeat="phone in user.phones">
        {{ phone }} <a href>Remove</a>
    </div>
</div>

为此,我需要创建 `$scope.removePhone` 和 `$scope.removeEmail`,并使用 `ngClick` 在“删除”链接上进行调用。但是,我正在寻找更通用的解决方案。特别是因为我有许多带有 `ngRepeats` 的页面。
我考虑编写一个指令,该指令将放置在“删除”链接上,并执行以下操作:
1. 在父元素中查找 `ngRepeat`。 2. 读取它正在迭代的内容(第一个示例中的“user.emails”,第二个示例中的“user.phones”)。 3. 从该模型中删除 `$index` 元素。
因此,标记看起来可能如下所示:
<div ng-controller="MyController">
    <div ng-repeat="email in user.emails">
        {{ email }} <a href remove-directive="$index">Remove</a>
    </div>

    <div ng-repeat="phone in user.phones">
        {{ phone }} <a href remove-directive="$index">Remove</a>
    </div>
</div>

我想知道我要实现的目标是否可能,并且应该采用哪种首选方法来实现?

当前的折中解决方案

这是我目前的做法。虽然不够优美但能完成任务,等我找到更好的方法再改进。

  myAppModule.controller('MyController', function ($scope, $parse, $routeParams, User) {
    $scope.user = User.get({id: $routeParams.id});

    $scope.remove = function ($index, $event) {
      // TODO: Find a way to make a directive that does this. This is ugly. And probably very wrong.
      var repeatExpr = $($event.currentTarget).closest('[ng-repeat]').attr('ng-repeat');
      var modelPath  = $parse(repeatExpr.split('in')[1].replace(/^\s+|\s+$/g, ''));

      $scope.$eval(modelPath).splice($index, 1);
    };
  });

在DOM中:

<div ng-repeat="email in user.email" class="control-group">
  <label class="control-label">
    {{ "Email Address"|_trans }}
  </label>

  <div class="controls">
    <input type="text" ng-model="email.address">

    <span class="help-inline"><a href ng-click="remove($index, $event)">{{ "Delete"|_trans }}</a></span>
  </div>
</div>

1
"无 JS" 是最佳答案。(在你只看投票最多的答案的情况下) - Dev Null
5个回答

79

你可以创建一个通用的remove方法,该方法接受数组和要删除的项作为参数。

<div ng-app="" ng-controller="MyController">
    <div ng-repeat="email in emails">{{ email }} <a ng-click="remove(emails, $index)">Remove</a>
    </div>
    <div ng-repeat="phone in phones">{{ phone }} <a ng-click="remove(phones, $index)">Remove</a>
    </div>
</div>

$scope.remove = function(array, index){
    array.splice(index, 1);
}

17
避免重复是理想的,但保持简单也非常重要。 - Mark Coleman
2
你并没有重复自己,而是在不同的位置使用不同的参数多次调用一个函数。最终目标是构建应用程序,因此应该注重实际效果。 ;) - Chandermani
1
也许有些偏题,但是当一个对象不是数组时,如何从ng-repeat中删除它?不确定如何将正确的对象传递到视图中进行删除。 - irth
5
有人注意到使用它时有延迟吗?似乎需要几秒钟才能从对象/数组中移除该项。 - allencoded
@allencoded 是的,它会,因为使用了 ngAnimate。一旦移除它,Angular 会给它添加一个 ng-leave 类,等待约0.2秒,然后将其从DOM中删除。只需使用CSS类以任何你想要的方式删除该元素即可。 - olivarra1
显示剩余2条评论

72

没有 JS

<div ng-repeat="option in options" ng-init=options=[1,2,3,4,5]>
   <button ng-click="options.splice($index,1)">Remove me</button>      
</div>

1
最简单、最容易、最好的使用Angular。 - asherrard
1
干得好,这正是我想要的。简明扼要,没有废话。 - Andrew Carr
1
嗯...有JavaScript。我想您的意思是“没有外部JS”。 - dǝɥɔS ʇoıןןƎ

19
<div ng-app="" ng-controller="MyController">
    <div ng-repeat="email in emails as datasource">{{ email }} 
        <a ng-click="datasource.splice($index,1)">Remove</a>
    </div>
    <div ng-repeat="phone in phones as datasource">{{ phone }} 
        <a ng-click="datasource.splice($index,1)">Remove</a>
    </div>
</div>

这可能是最好的答案。如果您没有验证并且没有软删除(从列表中删除但保留在内存中)要删除项目,则此方法非常优雅。如果您想要将“代码”保持在HTML声明之外,您可以随时将其包装为方法。 - Doug Chamberlain

3

一种非常简单和方便的跨浏览器工作方式是使用库Lodash中的'remove'实用方法。

<div ng-repeat="phone in phones">{{ phone }} 
  <a ng-click="removeItem(phones, phone)">Remove</a>
</div>

在您的控制器中声明如下:
//inject lodash dependency

//declare method in scope
$scope.removeItem = function(list, item){
   lodash.remove(list,function(someItem) { return item === someItem});
}

如果您喜欢,当然可以使用索引。请参见https://lodash.com/docs#remove


我知道这已经很老了,但值得指出的是,这个答案使用了特定的ng-lodash实现:https://github.com/rockabox/ng-lodash - dsal1951

1
如果您在对象上使用了ng-repeat而不是数组,请执行以下操作。
<div ng-app="" ng-controller="MyController">
    <div ng-repeat="email in emails">{{ email }} 
      <a ng-click="remove(emails, email)">Remove</a>
    </div>
    <div ng-repeat="phone in phones">{{ phone }} 
      <a ng-click="remove(phones, phone)">Remove</a>
    </div>
</div>

$scope.remove = function(objects, o){
    delete object[o.id];
}

或者更加简洁的方式。
<div ng-app="" ng-controller="MyController">
    <div ng-repeat="email in emails">{{ email }} 
      <a ng-click="delete emails[email.id]">Remove</a>
    </div>
    <div ng-repeat="phone in phones">{{ phone }} 
      <a ng-click="delete phones[phone.id]">Remove</a>
    </div>
</div>

假设这些对象看起来像这样。
var emails = {  '123' : { id : '123', .... }  };

var phones = {  '123' : { id : '123', .... }  };

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接