用ng-click单击复选框不会更新模型


85

单击复选框并调用ng-click:在ng-click插入之前不会更新模型,因此在UI中错误地显示了复选框的值:

这在AngularJS 1.0.7中有效,在Angualar 1.2-RCx中似乎已损坏。

<div ng-app="myApp" ng-controller="Ctrl">
<li  ng-repeat="todo in todos">
  <input type='checkbox' ng-click='onCompleteTodo(todo)' ng-model="todo.done">
    {{todo.text}}
</li> 
<hr>
task: {{todoText}}
<hr><h2>Wrong value</h2>
     done: {{doneAfterClick}}

和控制器:

angular.module('myApp', [])
  .controller('Ctrl', ['$scope', function($scope) {
    $scope.todos=[
        {'text': "get milk",
         'done': true
         },
        {'text': "get milk2",
         'done': false
         }
        ];


   $scope.onCompleteTodo = function(todo) {
    console.log("onCompleteTodo -done: " + todo.done + " : " + todo.text);
    $scope.doneAfterClick=todo.done;
    $scope.todoText = todo.text;

   };
}]);

带有Angular 1.2 RCx的破碎小提琴-http: //jsfiddle.net/supercobra/ekD3r/

使用Angular 1.0.0的工作混蛋-http: //jsfiddle.net/supercobra/8FQNw/


3
现在我已经将Angular更新为1.2+,这对我来说也很
困难

在v1.2.24中也已损坏。
文森特·P

Answers:


165

如何改变

<input type='checkbox' ng-click='onCompleteTodo(todo)' ng-model="todo.done">

<input type='checkbox' ng-change='onCompleteTodo(todo)' ng-model="todo.done">

文档

当用户更改输入时评估给定的表达式。当值更改来自模型时,不评估表达式。

注意,该指令必须ngModel存在。


3
这在版本1.2.7中似乎也被打破了
JvdBerg 2014年

神圣的灯泡,蝙蝠侠!我以为自己在做其他完全错误的事情,但是事实证明,这很简单。
亚当·马歇尔

1
很有帮助的答案!+1 Angular
Doc

如果您需要事件数据来阻止Default怎么办?
user1943442 2015年


9

ng-clickng-model执行的顺序不明确(因为两者均未明确设置它们的priority)。最稳定的解决方案是避免在同一元素上使用它们。

另外,您可能不希望示例显示的行为;您希望checkbox响应完整标签文本上的点击,而不仅仅是复选框。因此,最清洁的解决方案是包住input(有ng-model)内的label(与ng-click):

<label ng-click="onCompleteTodo(todo)">
  <input type='checkbox' ng-model="todo.done">
  {{todo.text}}
</label>

工作示例:http : //jsfiddle.net/b3NLH/1/


非常感谢!这是唯一对我有用的解决方案!
DaniCE

这个解决方案仍然是最好的!
Ellisan

8

你为什么不使用

$watch('todo',function(.....

或另一种解决方案是设置todo.doneng-click回调内部,仅使用ng-click

<div ng-app="myApp" ng-controller="Ctrl">
<li  ng-repeat="todo in todos">
<input type='checkbox' ng-click='onCompleteTodo(todo)'>
    {{todo.text}} {{todo.done}}

$scope.onCompleteTodo = function(todo) {
        todo.done = !todo.done; //toggle value
        console.log("onCompleteTodo -done: " + todo.done + " : " + todo.text);
        $scope.current = todo;
}

2
看到@kakoni答案,我使用ng-change而不是ng-click,并且计时效果很好。这使您可以保持双向绑定,并且这种方法更加简洁。
Michael Moser 2014年

6

用ng-checked代替ng-model对我来说很有效。


正是我想要的。谢谢!
以撒

刚刚从这里所有可用的解决方案为我工作。
thatzprem '16

2

这是一种hack,但是将其包装在超时中似乎可以完成您想要的操作:

angular.module('myApp', [])
    .controller('Ctrl', ['$scope', '$timeout', function ($scope, $timeout) {
    $scope.todos = [{
        'text': "get milk",
        'done': true
    }, {
        'text': "get milk2",
            'done': false
    }];

    $scope.onCompleteTodo = function (todo) {
        $timeout(function(){
            console.log("onCompleteTodo -done: " + todo.done + " : " + todo.text);
            $scope.doneAfterClick = todo.done;
            $scope.todoText = todo.text;
        });
    };
}]);

1

ng-model和之间的顺序ng-click似乎有所不同,您可能不应该依赖它。相反,您可以执行以下操作:

<div ng-app="myApp" ng-controller="Ctrl">
<li  ng-repeat="todo in todos">
<input type='checkbox' ng-model="todo.done" ng-click='onCompleteTodo(todo)'>
    {{todo.text}} {{todo.done}}
</li> 
    <hr>
        task: {{current.text}}
        <hr>
            <h2>Wrong value</h2>
         done: {{current.done}}
</div>

和您的脚本:

angular.module('myApp', [])
    .controller('Ctrl', ['$scope', function($scope) {

        $scope.todos=[
            {'text': "get milk",
             'done': true
             },
            {'text': "get milk2",
             'done': false
             }
            ];

        $scope.current = $scope.todos[0];


       $scope.onCompleteTodo = function(todo) {
            console.log("onCompleteTodo -done: " + todo.done + " : " + todo.text);
    //$scope.doneAfterClick=todo.done;
    //$scope.todoText = todo.text;
       $scope.current = todo;

   };
}]);

此处的不同之处在于,每当您单击一个框时,它将框设置为“当前”框,然后在视图中显示这些值。http://jsfiddle.net/QeR7y/


0

通常,这是由于ng-controller和输入之间的另一个指令正在创建新的作用域。当select写入它的值时,它将把它写入最近的作用域,因此它将把它写入此作用域,而不是更远的父对象。

最佳做法是永远不要直接绑定到范围内的变量ng-model,这也被称为在ngmodel中始终包含“点”。要对此进行更好的解释,请观看约翰的这段视频:

http://www.youtube.com/watch?v=DTx23w4z6Kc

解决方案来自:https : //groups.google.com/forum/#!topic/angular/7Nd_me5YrHU


如果您#t=5m08s在YouTube链接中提供了跳转标记,那就太好了,这样就不必观看完整的视频了。参见mattcutts.com/blog/link-to-youtube-minute-second
Volker E.

0

我只是替换ng-modelng-checked,它为我工作。

这个问题是我将我的角度版本从更新1.2.281.4.9

还要ng-change在这里检查是否引起任何问题。ng-change为了使它正常工作,我不得不拆除井筒。


-1
.task{ng:{repeat:'task in model.tasks'}}
  %input{type:'checkbox',ng:{model:'$parent.model.tasks[$index].enabled'}}
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.