Clicking a checkbox with ng-click does not update the model

By clicking on the flag and calling ng-click: the model is not updated before the ng-click exits, so the value of the flag is incorrectly presented in the user interface:

This works in AngularJS 1.0.7 and seems broken in 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}} 

and controller:

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

Broken fiddle w / Angular 1.2 RCx - http://jsfiddle.net/supercobra/ekD3r/

Working fidddle w / Angular 1.0.0 - http://jsfiddle.net/supercobra/8FQNw/

+76
angularjs checkbox
Oct 21 '13 at 14:09
source share
10 answers

How about a change

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

to

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

From docs :

Rate this expression when the user changes input. An expression is not evaluated when a change in value comes from a model.

Note. This directive requires ngModel .

+143
Nov 22 '13 at 11:30
source share

As reported at https://github.com/angular/angular.js/issues/4765 switching from ng-click to ng-change seems like a fix (I'm using Angular 1.2.14)

+11
Mar 05 '14 at 18:06
source share

The order in which ng-click and ng-model will be executed is ambiguous (since none of them explicitly sets their priority ). The most sustainable solution for this would be to avoid using them on a single element.

Also, you probably don't want the behavior to show examples; you want the checkbox respond to clicks on the full text of the label, and not just on the checkbox. Therefore, the purest solution would be to wrap the input (with ng-model ) inside the label (using ng-click ):

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

Working example: http://jsfiddle.net/b3NLH/1/

+8
Oct 21 '13 at 14:27
source share

Why aren't you using

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

Or another solution would be to set todo.done inside the ng-click callback and use only 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}} 

and

 $scope.onCompleteTodo = function(todo) { todo.done = !todo.done; //toggle value console.log("onCompleteTodo -done: " + todo.done + " : " + todo.text); $scope.current = todo; } 
+8
Oct. 21 '13 at 15:55
source share

Replacing the ng model with ng-checked works for me.

+6
Aug 16 '16 at 19:38
source share

This is a kind of hack, but its completion in a timeout seems to accomplish what you are looking for:

 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; }); }; }]); 
+2
Oct 21 '13 at 14:23
source share

The order between ng-model and ng-click seems different, and you probably shouldn't rely on it. Instead, you can do something like this:

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

And your script:

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

What makes it different every time you click a field, it sets that field to "current" and then displays these values ​​in the view. http://jsfiddle.net/QeR7y/

+1
Oct 21 '13 at 14:34
source share

This is usually due to a different directive between your ng controller and your input creating a new scope. When you record a selection, enter its value, it will write it to the very last area, so it will write it to this scope, not the parent, far away.

The best practice is to never bind directly to a variable in an area in the ng-model , it is also known, as always, by including a β€œpoint” in your ng model. For a better explanation of this, check out this video from John:

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

Solution from: https://groups.google.com/forum/#!topic/angular/7Nd_me5YrHU

0
Jun 11 '14 at 1:55
source share

I just replaced ng-model with ng-checked and it worked for me.

This problem occurred when I upgraded the angular version from 1.2.28 to 1.4.9

Also check if your ng-change is causing all the problems. I had to delete my ng-change somehow in order for it to work.

0
Oct 24 '16 at 11:04 on
source share
 .task{ng:{repeat:'task in model.tasks'}} %input{type:'checkbox',ng:{model:'$parent.model.tasks[$index].enabled'}} 
-one
Mar 29 '15 at 23:36
source share



All Articles