简体   繁体   English

点击后AngularJS中的复选框“双重检查”

[英]Checkbox in AngularJS “double checking” after click

I'm trying to make a simple to do list app using Angular. 我正在尝试使用Angular创建一个简单的列表应用程序。 When the user clicks the checkbox, the list item should disappear. 当用户单击该复选框时,列表项应该消失。 Right now, the list item disappears upon clicking the checkbox, but the checkbox of the list item directly below it also gets checked (although the list item doesn't disappear). 现在,列表项在单击复选框后消失,但是直接在它下面的列表项的复选框也会被检查(尽管列表项不会消失)。

<ul ng-repeat="item in arr track by $index">
    <li>
        <input type="checkbox" ng-click="check(item)">
        <span>{{ item }}</span>
    </li>
</ul>

$scope.arr = [
    'todo 1',
    'todo 2',
    'todo 3'
];

$scope.check = function(item) {
    var indexOf = $scope.arr.indexOf(item);
    if (indexOf !== -1) {
        $scope.arr.splice(indexOf, 1);
    }
};

Is there any way to solve this? 有什么方法可以解决这个问题吗?

The checkbox directly under the deleted item was automatically being checked because the information, that first the element in array is checked was still valid, but the length of the array reduces with every splice method executed. 直接在已删除项目下面的复选框被自动检查,因为首先检查数组中元素的信息仍然有效,但是每次执行splice方法时,数组的长度都会减少。 That's why you have to actually tell angular that check another element, which takes index: 0 in the array after previous element gets spliced is unnecessary . 这就是为什么你必须实际告诉angular检查另一个元素,在前一个元素被拼接之后,数组中的index: 0不必要的

Here's the solution: Plunker link 这是解决方案: Plunker链接

Raw code: 原始代码:

<ul ng-repeat="item in arr track by $index">
  <li>
    <input type="checkbox" ng-click="check(item)" ng-model="item.selected">
    <span>{{ item }}</span>
  </li>
</ul>


$scope.arr = [
  'todo 1',
  'todo 2',
  'todo 3'
];

$scope.check = function(item) {
  var indexOf = $scope.arr.indexOf(item);
  if (indexOf !== -1) {
    $scope.arr.splice(indexOf, 1);
    $scope.item.selected = false;
}

Not sure how this is working as-is, but the normal way to accomplish this is with an ng-model on the <input> . 不知道这是如何工作的,但实现这一目标的正常方法是使用<input>上的ng-model Make your items into objects so they can store more complex state, which also lets you drop track by . 将您的项目变为对象,以便它们可以存储更复杂的状态,这也可以让您放弃track by

<ul ng-repeat="item in arr">
  <li>
    <input type="checkbox" ng-model="item.done">
    <span>{{item.label}}</span>
  </li>
</ul>

$scope.arr = [
  {label: 'todo 1', done: false},
  {label: 'todo 2', done: false},
  {label: 'todo 3', done: false}
];

That should get your checking and unchecking set up correctly. 这应该可以正确设置您的检查和取消选中。 To drop items when they're done, I recommend a filer on the ng-repeat . 要在项目完成后删除项目,我建议在ng-repeat上使用文件管理器。

ng-repeat="item in arr | filter: {done: 'false'}"

https://plnkr.co/edit/ybikvwysC6ZEd7CeZnnt?p=preview https://plnkr.co/edit/ybikvwysC6ZEd7CeZnnt?p=preview

That happens because you use "track by $index". 这是因为你使用“跟踪$ index”。 Try without track by, or use track by with some unique field (id), in which case your list should consist of objects, not primitives. 尝试没有跟踪,或使用跟踪一些唯一字段(id),在这种情况下,您的列表应包含对象,而不是基元。 For example: 例如:

$scope.arr = [
  {id: 1, name: 'todo 1'},
  {id: 2, name: 'todo 2'},
  {id: 3, name: 'todo 3'} //...
];

<ul ng-repeat="item in arr track by item.id">
    <li>
        <input type="checkbox" ng-click="check($index)">
        <span>{{item.name}}</span>
    </li>
</ul>

$scope.check = function(index) {
    $scope.arr.splice(index, 1);
}

You need to prevent the click event from performing the default action 您需要阻止click事件执行默认操作

 <input type="checkbox" ng-click="check(item);$event.preventDefault();" />

Angular is removing the element, on the click, but then the (moved) element also gets the click event, checking it. Angular在点击时删除了元素,但是(移动的)元素也获得了click事件,检查它。 $event.preventDefault() will prevent this. $ event.preventDefault()将阻止这种情况。

Here is a working plunk 这是一个工作的插件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM