【问题标题】:How do I delete an item or object from an array using ng-click?如何使用 ng-click 从数组中删除项目或对象?
【发布时间】:2013-03-05 10:35:01
【问题描述】:

我正在尝试编写一个函数,使我能够在单击按钮时删除一个项目,但我认为我对该函数感到困惑 - 我是否使用 $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();
};

【问题讨论】:

  • 您不需要 $digest,因为它用于进入 Angular 的摘要循环(并且由于 ng-click,您已经处于摘要循环中)。您是否尝试从数组中删除项目?
  • @MarkRajcok :) 是的,这就是我想要做的
  • remove() in ng-click 你拥有它的方式没有上下文。需要在标记中提供更多详细信息以显示要删除的内容以及它是否在 ng-repeat 内,或者要删除的项目来自哪里,或者您希望 remove() 的行为是什么
  • @charlietfl 它在 ng-repeat 我已经更新了问题

标签: html angularjs edit


【解决方案1】:

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

<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 创建的服务来管理阵列更新,同时它会更新服务器

【讨论】:

  • 直接使用$index 如果您的列表在模板上被过滤,则会产生错误。这是一个模板的东西;使用ng-click='remove(bday)' 然后使用arr.splice(arr.indexOf(bday),1); 更安全
  • 你不需要传递$index,因为你可以在方法中使用'this'。 $scope.remove = function(){ $scope.bdays.splice(this.$index, 1); }
  • @matthewdavidson this is undefined。 Plunker/jsfiddle 也许?
  • .indexOf(item) 如果未找到将返回 -1,如果您不检查它可能会导致删除数组末尾的项目。
  • @ShibinRagh 阅读Array.prototype.splice()的文档
【解决方案2】:

这是一个正确的答案:

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

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

【讨论】:

  • 看起来两个答案是等效的,尽管您的函数可以接受没有 $ 的索引并且它仍然可以工作。
  • 这应该是正确的答案。 indexOf 仅适用于 IE9+
  • 如果您的 ng-repeat 中有 orderBy 或过滤器,这将不起作用
  • 如果你使用了 track by $index 会更好
  • @Joan-DiegoRodriguez 如果您有过滤器/订单,您将如何使其工作?没关系,只需阅读 XMLilley 的 Answer
【解决方案3】:

如果您在 ng-repeat 中

您可以使用单线选项

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

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

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

【讨论】:

  • 我喜欢并用过这一款
【解决方案4】:

使用$index 在基本情况下效果很好,@charlietfl 的回答很棒。但有时,$index 还不够。

想象一下,您有一个数组,它以两个不同的 ng-repeat 呈现。其中一个 ng-repeat 被过滤为具有真实属性的对象,另一个被过滤为虚假属性。展示了两个不同的过滤数组,它们源自一个原始数组。 (或者,如果它有助于可视化:也许你有一个人数组,并且你想要一个 ng-repeat 用于该数组中的女性,另一个用于 同一数组中的男性。)您的目标:使用来自已过滤数组成员的信息可靠地从原始数组中删除。

在每个过滤后的数组中,$index 不会是原始数组中项目的索引。它将是过滤后的子数组中的索引。因此,您将无法知道原始 people 数组中的人的索引,您只能从 womenmen 子数组中知道 $index。尝试使用它来删除,除了你想要的地方,你的项目会从任何地方消失。怎么办?

如果您足够幸运,使用的数据模型包含每个对象的唯一标识符,那么请使用它而不是 $index,从主数组中查找对象和splice。 (在下面使用我的示例,但使用该唯一标识符。)但是,如果您不那么幸运呢?

Angular 实际上使用称为$$hashKey 的唯一属性来扩充 ng 重复数组(在主原始数组中)中的每个项目。您可以在原始数组中搜索要删除的项目的 $$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 上而不是特定于模型的属性名称上,还具有使该函数可跨不同模型和上下文重用的显着附加优势。为它提供您的数组引用和您的项目引用,它应该可以正常工作。

【讨论】:

    【解决方案5】:

    我通常是这样写的:

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

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

    【讨论】:

    • (index, 1)中的“1”是什么意思
    • @ShibinRagh 这是deleteCount一个整数,表示要删除的旧数组元素的数量。如果 deleteCount 为 0,则不删除任何元素。在这种情况下,您应该至少指定一个新元素。如果 deleteCount 大于从 start 开始的数组中剩余的元素数,则将删除数组末尾的所有元素。 Array.prototype.splice() Documentation
    【解决方案6】:

    在接受的答案的基础上,这将适用于 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 = {remove: function(){...}},那么它会。
    【解决方案7】:

    没有控制器的实现。

    <!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)
    

    索引: 必需的。一个整数,指定在什么位置添加/删除项目,使用负值指定从数组末尾开始的位置。

    多少项目:可选。要删除的项目数。如果设置为 0,则不会删除任何项目。

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

    【讨论】:

    • 这是正确的答案。为什么要依赖控制器来执行简单的 JavaScript 调用?
    【解决方案8】:

    我不同意您应该在控制器上调用方法。您应该为任何实际功能使用服务,并且应该为任何功能定义指令以实现可伸缩性和模块化,并分配一个单击事件,其中包含对您注入指令的服务的调用。

    例如,在您的 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 中没有控制器。 :)

    开发愉快!!!

    【讨论】:

      【解决方案9】:

      这是另一个答案。我希望它会有所帮助。

      <a class="btn" ng-click="delete(item)">Delete</a>
      
      $scope.delete(item){
       var index = this.list.indexOf(item);
                      this.list.splice(index, 1);   
      }
      
      array.splice(start)
      array.splice(start, deleteCount)
      array.splice(start, deleteCount, item1, item2, ...)
      

      完整来源在这里
      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice

      【讨论】:

        【解决方案10】:

        如果您的商品中有 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
                        });
        }
        

        【讨论】:

          【解决方案11】:
          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);
            }
          

          【讨论】:

            【解决方案12】:

            一个简单的内联方法是在删除按钮中添加bdays.splice($index, 1)

              <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="bdays.splice($index, 1)">Delete</a>
                </form>
              </li>
            </ul>
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2021-08-01
              • 1970-01-01
              • 2015-08-27
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多