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

时间:2022-08-25 23:27:45

I am trying to write a function that enables me to remove an item when the button is clicked but I think I am getting confused with the function - do I use $digest?

我正在尝试编写一个函数,当单击按钮时,它可以让我删除一个项目,但我认为我对这个函数感到困惑——我是否使用了$digest?

HTML & app.js:

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

9 个解决方案

#1


501  

To remove item you need to remove it from array and can pass bday item to your remove function in markup. Then in controller look up the index of item and remove from array

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

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

Then in controller:

然后在控制器:

$scope.remove = function(item) { 
  var index = $scope.bdays.indexOf(item);
  $scope.bdays.splice(index, 1);     
}

Angular will automatically detect the change to the bdays array and do the update of ng-repeat

角将自动检测到bdays数组的更改,并执行ng-repeat的更新。

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

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

EDIT: If doing live updates with server would use a service you create using $resource to manage the array updates at same time it updates server

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

#2


50  

This is a correct answer:

这是一个正确的答案:

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

In @charlietfl's answer. I think it's wrong since you pass $index as paramter but you use the wish instead in controller. Correct me if I'm wrong :)

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

#3


24  

in case you're inside an ng-repeat

you could use a one liner option

您可以使用一个线性选项

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

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

$index is used by angular to show current index of the array inside an ng-repeat

$index是角化的,用于显示ng-repeat中数组的当前索引

#4


22  

Using $index works perfectly well in basic cases, and @charlietfl's answer is great. But sometimes, $index isn't enough.

在基本情况下,使用$index非常有效,@charlietfl的答案很好。但有时,仅凭指数是不够的。

Imagine you have a single array, which you're presenting in two different ng-repeat's. One of those ng-repeat's is filtered for objects that have a truthy property, and the other is filtered for a falsy property. Two different filtered arrays are being presented, which derive from a single original array. (Or, if it helps to visualize: perhaps you have a single array of people, and you want one ng-repeat for the women in that array, and another for the men in that same array.) Your goal: delete reliably from the original array, using information from the members of the filtered arrays.

假设你有一个数组,你用两个不同的ng-repeat来表示它。其中一个ng-repeat被过滤为具有真实属性的对象,另一个则被过滤为虚假属性。两种不同的过滤阵列被呈现出来,它们来自一个原始的数组。(或者,如果它有助于形象化的话:也许你有一组人,你想要一个在那个组里的女人重复的ng,另一个在那个组里的男人重复)您的目标:使用来自过滤数组成员的信息,可靠地从原始数组中删除。

In each of those filtered arrays, $index won't be the index of the item within the original array. It'll be the index in the filtered sub-array. So, you won't be able to tell the person's index in the original people array, you'll only know the $index from the women or men sub-array. Try to delete using that, and you'll have items disappearing from everywhere except where you wanted. What to do?

在每个经过过滤的数组中,$index都不是原始数组中项的索引。它将是过滤子数组中的索引。所以,你不能在原始的people数组中告诉person的索引,你只能知道$index来自于women或men的子数组。试着用它来删除,你会发现除了你想要的地方,其他地方的东西都会消失。要做什么吗?

If you're lucky enough be using a data model includes a unique identifier for each object, then use that instead of $index, to find the object and splice it out of the main array. (Use my example below, but with that unique identifier.) But if you're not so lucky?

如果您足够幸运,可以使用包含每个对象的唯一标识符的数据模型,那么使用它而不是使用$index来查找对象并将其从主数组中拼接出来。(请使用下面的示例,但是要使用唯一标识符。)但如果你没那么幸运呢?

Angular actually augments each item in an ng-repeated array (in the main, original array) with a unique property called $$hashKey. You can search the original array for a match on the $$hashKey of the item you want to delete, and get rid of it that way.

实际上,使用一个名为$hashKey的惟一属性,使ng-repeat数组(主数组中为原始数组)中的每一项都增加了。您可以在原始数组中搜索要删除的项目的$hashKey上的匹配项,然后以这种方式删除它。

Note that $$hashKey is an implementation detail, not included in the published API for ng-repeat. They could remove support for that property at any time. But probably not. :-)

注意,$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;
    };
  });
}

Invoke with:

调用:

ng-click="deleteFilteredItem(item.$$hashKey, refToSourceArray)"

EDIT: Using a function like this, which keys on the $$hashKey instead of a model-specific property name, also has the significant added advantage of making this function reusable across different models and contexts. Provide it with your array reference, and your item reference, and it should just work.

编辑:使用这样的函数,在$$hashKey上键而不是特定于模型的属性名上键,也有显著的额外优势,可以使这个函数在不同的模型和上下文中可重用。为它提供数组引用和项引用,它应该就可以工作了。

#5


8  

Building on the accepted answer, this will work with ngRepeat, filterand handle expections better:

根据公认的答案,这将与ngRepeat, filterand处理期望更好:

Controller:

控制器:

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

View:

观点:

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

#6


7  

I usually write in such style :

我通常是这样写的:

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


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

Hope this will help

希望这将帮助

#7


3  

I disagree that you should be calling a method on your controller. You should be using a service for any actual functionality, and you should be defining directives for any functionality for scalability and modularity, as well as assigning a click event which contains a call to the service which you inject into your directive.

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

So, for instance, on your HTML...

例如,在你的HTML上。

<a class="btn" ng-remove-birthday="$index">Delete</a>

Then, create a directive...

然后,创建一个指令……

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

Then in your service...

然后在你的服务……

angular.module('myApp').factory('myService', [function(){
    return {
        removeBirthday: function(birthdayIndex, scope){
            scope.bdays.splice(birthdayIndex);
            scope.$apply();
        }
    };
}]);

When you write your code properly like this, you will make it very easy to write future changes without having to restructure your code. It's organized properly, and you're handling custom click events correctly by binding using custom directives.

当您像这样正确地编写代码时,您将非常容易地编写将来的更改,而不必重构代码。它是正确组织的,并且您正在通过使用自定义指示来正确地处理自定义的单击事件。

For instance, if your client says, "hey, now let's make it call the server and make bread, and then popup a modal." You will be able to easily just go to the service itself without having to add or change any of the HTML, and/or controller method code. If you had just the one line on the controller, you'd eventually need to use a service, for extending the functionality to the heavier lifting the client is asking for.

例如,如果你的客户说,“嘿,现在让它调用服务器,做面包,然后弹出一个模态。”您可以轻松地访问服务本身,而无需添加或更改任何HTML和/或控制器方法代码。如果您只有控制器上的一行,那么您最终需要使用一个服务,将功能扩展到客户机要求的更大的提升。

Also, if you need another 'Delete' button elsewhere, you now have a directive attribute ('ng-remove-birthday') you can easily assign to any element on the page. This now makes it modular and reusable. This will come in handy when dealing with the HEAVY web components paradigm of Angular 2.0. There IS no controller in 2.0. :)

另外,如果你在其他地方需要另一个“删除”按钮,你现在有了一个指令属性(“ng-remove-birthday”),你可以很容易地将它分配给页面上的任何元素。这使得它成为模块化和可重用的。在处理角度2.0的web组件范例时,这将非常有用。在2.0中没有控制器。:)

Happy Developing!!!

发展快乐! ! !

#8


2  

implementation Without a Controller.

没有一个控制器实现。

<!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">{{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>

The splice() method adds/removes items to/from an array.

splice()方法将项添加/删除到数组中。

array.splice(index, howmanyitem(s), item_1, ....., item_n)

index: Required. An integer that specifies at what position to add/remove items, Use negative values to specify the position from the end of the array.

指数:必需的。指定在什么位置添加/删除项目的整数,使用负值来指定数组末尾的位置。

howmanyitem(s): Optional. The number of items to be removed. If set to 0, no items will be removed.

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

item_1, ..., item_n: Optional. The new item(s) to be added to the array

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

#9


1  

Here is another answer. I hope it will help.

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

<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, ...)

Full source is here
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice

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

#1


501  

To remove item you need to remove it from array and can pass bday item to your remove function in markup. Then in controller look up the index of item and remove from array

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

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

Then in controller:

然后在控制器:

$scope.remove = function(item) { 
  var index = $scope.bdays.indexOf(item);
  $scope.bdays.splice(index, 1);     
}

Angular will automatically detect the change to the bdays array and do the update of ng-repeat

角将自动检测到bdays数组的更改,并执行ng-repeat的更新。

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

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

EDIT: If doing live updates with server would use a service you create using $resource to manage the array updates at same time it updates server

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

#2


50  

This is a correct answer:

这是一个正确的答案:

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

In @charlietfl's answer. I think it's wrong since you pass $index as paramter but you use the wish instead in controller. Correct me if I'm wrong :)

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

#3


24  

in case you're inside an ng-repeat

you could use a one liner option

您可以使用一个线性选项

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

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

$index is used by angular to show current index of the array inside an ng-repeat

$index是角化的,用于显示ng-repeat中数组的当前索引

#4


22  

Using $index works perfectly well in basic cases, and @charlietfl's answer is great. But sometimes, $index isn't enough.

在基本情况下,使用$index非常有效,@charlietfl的答案很好。但有时,仅凭指数是不够的。

Imagine you have a single array, which you're presenting in two different ng-repeat's. One of those ng-repeat's is filtered for objects that have a truthy property, and the other is filtered for a falsy property. Two different filtered arrays are being presented, which derive from a single original array. (Or, if it helps to visualize: perhaps you have a single array of people, and you want one ng-repeat for the women in that array, and another for the men in that same array.) Your goal: delete reliably from the original array, using information from the members of the filtered arrays.

假设你有一个数组,你用两个不同的ng-repeat来表示它。其中一个ng-repeat被过滤为具有真实属性的对象,另一个则被过滤为虚假属性。两种不同的过滤阵列被呈现出来,它们来自一个原始的数组。(或者,如果它有助于形象化的话:也许你有一组人,你想要一个在那个组里的女人重复的ng,另一个在那个组里的男人重复)您的目标:使用来自过滤数组成员的信息,可靠地从原始数组中删除。

In each of those filtered arrays, $index won't be the index of the item within the original array. It'll be the index in the filtered sub-array. So, you won't be able to tell the person's index in the original people array, you'll only know the $index from the women or men sub-array. Try to delete using that, and you'll have items disappearing from everywhere except where you wanted. What to do?

在每个经过过滤的数组中,$index都不是原始数组中项的索引。它将是过滤子数组中的索引。所以,你不能在原始的people数组中告诉person的索引,你只能知道$index来自于women或men的子数组。试着用它来删除,你会发现除了你想要的地方,其他地方的东西都会消失。要做什么吗?

If you're lucky enough be using a data model includes a unique identifier for each object, then use that instead of $index, to find the object and splice it out of the main array. (Use my example below, but with that unique identifier.) But if you're not so lucky?

如果您足够幸运,可以使用包含每个对象的唯一标识符的数据模型,那么使用它而不是使用$index来查找对象并将其从主数组中拼接出来。(请使用下面的示例,但是要使用唯一标识符。)但如果你没那么幸运呢?

Angular actually augments each item in an ng-repeated array (in the main, original array) with a unique property called $$hashKey. You can search the original array for a match on the $$hashKey of the item you want to delete, and get rid of it that way.

实际上,使用一个名为$hashKey的惟一属性,使ng-repeat数组(主数组中为原始数组)中的每一项都增加了。您可以在原始数组中搜索要删除的项目的$hashKey上的匹配项,然后以这种方式删除它。

Note that $$hashKey is an implementation detail, not included in the published API for ng-repeat. They could remove support for that property at any time. But probably not. :-)

注意,$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;
    };
  });
}

Invoke with:

调用:

ng-click="deleteFilteredItem(item.$$hashKey, refToSourceArray)"

EDIT: Using a function like this, which keys on the $$hashKey instead of a model-specific property name, also has the significant added advantage of making this function reusable across different models and contexts. Provide it with your array reference, and your item reference, and it should just work.

编辑:使用这样的函数,在$$hashKey上键而不是特定于模型的属性名上键,也有显著的额外优势,可以使这个函数在不同的模型和上下文中可重用。为它提供数组引用和项引用,它应该就可以工作了。

#5


8  

Building on the accepted answer, this will work with ngRepeat, filterand handle expections better:

根据公认的答案,这将与ngRepeat, filterand处理期望更好:

Controller:

控制器:

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

View:

观点:

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

#6


7  

I usually write in such style :

我通常是这样写的:

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


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

Hope this will help

希望这将帮助

#7


3  

I disagree that you should be calling a method on your controller. You should be using a service for any actual functionality, and you should be defining directives for any functionality for scalability and modularity, as well as assigning a click event which contains a call to the service which you inject into your directive.

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

So, for instance, on your HTML...

例如,在你的HTML上。

<a class="btn" ng-remove-birthday="$index">Delete</a>

Then, create a directive...

然后,创建一个指令……

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

Then in your service...

然后在你的服务……

angular.module('myApp').factory('myService', [function(){
    return {
        removeBirthday: function(birthdayIndex, scope){
            scope.bdays.splice(birthdayIndex);
            scope.$apply();
        }
    };
}]);

When you write your code properly like this, you will make it very easy to write future changes without having to restructure your code. It's organized properly, and you're handling custom click events correctly by binding using custom directives.

当您像这样正确地编写代码时,您将非常容易地编写将来的更改,而不必重构代码。它是正确组织的,并且您正在通过使用自定义指示来正确地处理自定义的单击事件。

For instance, if your client says, "hey, now let's make it call the server and make bread, and then popup a modal." You will be able to easily just go to the service itself without having to add or change any of the HTML, and/or controller method code. If you had just the one line on the controller, you'd eventually need to use a service, for extending the functionality to the heavier lifting the client is asking for.

例如,如果你的客户说,“嘿,现在让它调用服务器,做面包,然后弹出一个模态。”您可以轻松地访问服务本身,而无需添加或更改任何HTML和/或控制器方法代码。如果您只有控制器上的一行,那么您最终需要使用一个服务,将功能扩展到客户机要求的更大的提升。

Also, if you need another 'Delete' button elsewhere, you now have a directive attribute ('ng-remove-birthday') you can easily assign to any element on the page. This now makes it modular and reusable. This will come in handy when dealing with the HEAVY web components paradigm of Angular 2.0. There IS no controller in 2.0. :)

另外,如果你在其他地方需要另一个“删除”按钮,你现在有了一个指令属性(“ng-remove-birthday”),你可以很容易地将它分配给页面上的任何元素。这使得它成为模块化和可重用的。在处理角度2.0的web组件范例时,这将非常有用。在2.0中没有控制器。:)

Happy Developing!!!

发展快乐! ! !

#8


2  

implementation Without a Controller.

没有一个控制器实现。

<!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">{{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>

The splice() method adds/removes items to/from an array.

splice()方法将项添加/删除到数组中。

array.splice(index, howmanyitem(s), item_1, ....., item_n)

index: Required. An integer that specifies at what position to add/remove items, Use negative values to specify the position from the end of the array.

指数:必需的。指定在什么位置添加/删除项目的整数,使用负值来指定数组末尾的位置。

howmanyitem(s): Optional. The number of items to be removed. If set to 0, no items will be removed.

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

item_1, ..., item_n: Optional. The new item(s) to be added to the array

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

#9


1  

Here is another answer. I hope it will help.

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

<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, ...)

Full source is here
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice

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