Cliquer sur une case à cocher avec ng-click ne met pas à jour le modèle

En cliquant sur une case à cocher et en appelant ng-click: le modèle n’est pas mis à jour avant que ng-click intervienne, de sorte que la valeur de la case à cocher est présentée à tort dans l’interface utilisateur:

Cela fonctionne dans AngularJS 1.0.7 et semble cassé dans Angualar 1.2-RCx.

  • {{todo.text}}

  • task: {{todoText}}

    Wrong value

    done: {{doneAfterClick}}

    et contrôleur:

     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/

    Travailler avec un angular 1.0.0 – http://jsfiddle.net/supercobra/8FQNw/

    Que diriez-vous de changer

      

    à

      

    De docs :

    Évaluer l’expression donnée lorsque l’utilisateur modifie l’entrée. L’expression n’est pas évaluée lorsque le changement de valeur provient du modèle.

    Notez que cette directive nécessite la ngModel de ngModel .

    Comme indiqué dans https://github.com/angular/angular.js/issues/4765 , passer de ng-click à ng-change semble résoudre ce problème (j’utilise Angular 1.2.14)

    L’ordre dans lequel ng-click et ng-model seront exécutés est ambigu (car aucun d’eux ne définit explicitement leur priority ). La solution la plus stable serait d’éviter de les utiliser sur le même élément.

    En outre, vous ne voulez probablement pas le comportement que les exemples montrent; vous souhaitez que la checkbox à checkbox réponde aux clics sur le texte complet de l’ étiquette , et pas seulement à la case à cocher. Par conséquent, la solution la plus propre serait d’envelopper l’ input (avec ng-model ) dans une label (avec ng-click ):

      

    Exemple de travail: http://jsfiddle.net/b3NLH/1/

    Pourquoi ne pas utiliser

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

    Ou une autre solution serait de définir le todo.done dans le callback ng-click et d’utiliser uniquement ng-click

     
  • {{todo.text}} {{todo.done}}
  • et

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

    Remplacement du ng-model avec ng-checked fonctionne pour moi.

    C’est un peu un hack, mais l’enroulement dans un timeout semble accomplir ce que vous recherchez:

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

    L’ordre entre ng-model et ng-click semble être différent et c’est quelque chose que vous ne devriez probablement pas utiliser. Au lieu de cela, vous pourriez faire quelque chose comme ceci:

     
  • {{todo.text}} {{todo.done}}

  • task: {{current.text}}

    Wrong value

    done: {{current.done}}

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

    Ce qui est différent ici, c’est lorsque vous cliquez sur une case, elle définit cette case comme étant “actuelle” et affiche ensuite ces valeurs dans la vue. http://jsfiddle.net/QeR7y/

    Cela est généralement dû à une autre directive entre votre contrôleur ng et votre entrée qui crée une nouvelle scope. Lorsque la sélection enregistre la valeur, elle l’écrira jusqu’à la scope la plus récente, elle l’écrira donc dans cette scope plutôt que dans le parent plus éloigné.

    La meilleure pratique consiste à ne jamais se lier directement à une variable de la scope dans un ng-model , cela étant également connu comme comportant toujours un “point” dans votre modèle ng. Pour une meilleure explication, consultez cette vidéo de John:

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

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

    Je viens de remplacer ng-model avec ng-checked et cela a fonctionné pour moi.

    Ce problème était quand j’ai mis à jour ma version angular de 1.2.28 à 1.4.9

    Vérifiez également si votre ng-change cause un problème ici. J’ai dû enlever mon ng-change aussi bien pour le faire fonctionner.

     .task{ng:{repeat:'task in model.tasks'}} %input{type:'checkbox',ng:{model:'$parent.model.tasks[$index].enabled'}}