【问题标题】:Clicking a checkbox with ng-click does not update the model使用 ng-click 单击复选框不会更新模型
【发布时间】:2013-10-30 01:56:35
【问题描述】:

单击一个复选框并调用 ng-click:在 ng-click 启动之前模型未更新,因此该复选框值错误地显示在 UI 中:

这在 AngularJS 1.0.7 中有效,在 Angular 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/

【问题讨论】:

  • 现在我已经把 Angular 更新到 1.2+ 了
  • 在 v1.2.24 中也有问题。

标签: angularjs checkbox


【解决方案1】:

换个方式

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

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

来自docs

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

注意,该指令要求 ngModel 存在。

【讨论】:

  • 这似乎在 1.2.7 版本中也被破坏了
  • 圣灯泡,蝙蝠侠!我以为我在做其他完全错误的事情,但结果就这么简单。
  • 非常有帮助的答案! +1 Angular 文档 -1
  • 如果您需要事件数据来防止默认怎么办?
【解决方案2】:

正如https://github.com/angular/angular.js/issues/4765 中所报告的,从 ng-click 切换到 ng-change 似乎可以解决这个问题(我使用的是 Angular 1.2.14)

【讨论】:

  • 最简单最简单的修复。 +1 给格里芬多 :)
【解决方案3】:

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/

【讨论】:

  • 非常感谢!这是唯一对我有用的解决方案!
  • 这个方案还是最好的!
【解决方案4】:

你为什么不使用

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

或者另一种解决方案是在 ng-click 回调中设置 todo.done 并且只使用 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;
}

【讨论】:

  • 查看@kakoni 的回答,我使用了 ng-change 而不是 ng-click,而且时机很好。这使您可以保持双向绑定,并且方法更加简洁。
【解决方案5】:

用 ng-checked 替换 ng-model 对我有用。

【讨论】:

  • 正是我想要的。谢谢!
  • 刚刚从这里所有可用的解决方案中为我工作。
【解决方案6】:

这是一种 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;
        });
    };
}]);

【讨论】:

    【解决方案7】:

    ng-modelng-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/

    【讨论】:

      【解决方案8】:

      通常这是由于 ng-controller 之间的另一个指令 以及您正在创建新范围的输入。 When the select writes 输出它的值,它将把它写到最近的范围内,所以它 会将其写入此范围而不是更远的父级 离开。

      最好的做法是永远不要直接绑定到作用域上的变量 在ng-model 中,这也被称为总是包含一个“点” 你的 ngmodel。要更好地解释这一点,请查看此视频 来自约翰:

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

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

      【讨论】:

      【解决方案9】:

      我刚刚用ng-checked 替换了ng-model,它对我有用。

      当我将我的 Angular 版本从 1.2.28 更新为 1.4.9 时出现此问题

      还要检查您的ng-change 是否在此处引起任何问题。我还必须删除我的 ng-change 才能使其正常工作。

      【讨论】:

        【解决方案10】:
        .task{ng:{repeat:'task in model.tasks'}}
          %input{type:'checkbox',ng:{model:'$parent.model.tasks[$index].enabled'}}
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-08-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-12-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多