Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 角度:复选框组';的验证与模型不同步_Javascript_Angularjs_Angularjs Scope_Angularjs Validation_Angularjs Digest - Fatal编程技术网

Javascript 角度:复选框组';的验证与模型不同步

Javascript 角度:复选框组';的验证与模型不同步,javascript,angularjs,angularjs-scope,angularjs-validation,angularjs-digest,Javascript,Angularjs,Angularjs Scope,Angularjs Validation,Angularjs Digest,该复选框组要求至少选中一个复选框,以便启用“提交”按钮。 取消选中所有复选框将禁用该按钮。 所有复选框都使用相同的范围属性(showRequired)将其标记为所需 发生的情况是,第一次单击并没有像应该的那样启用按钮。选择和取消选择其他复选框会使整个事情变得不正常;无论复选框处于何种状态,在任何给定的单击中都可能启用或不启用该按钮 令人不安的是,我看到类ng valid并不总是应用于所有复选框。有时它在一个复选框上,有时它在所有复选框上,或者它们的一些组合上。使用$timeout可以修复所有问题

该复选框组要求至少选中一个复选框,以便启用“提交”按钮。
取消选中所有复选框将禁用该按钮。
所有复选框都使用相同的范围属性(showRequired)将其标记为所需

发生的情况是,第一次单击并没有像应该的那样启用按钮。选择和取消选择其他复选框会使整个事情变得不正常;无论复选框处于何种状态,在任何给定的单击中都可能启用或不启用该按钮

令人不安的是,我看到类ng valid并不总是应用于所有复选框。有时它在一个复选框上,有时它在所有复选框上,或者它们的一些组合上。使用$timeout可以修复所有问题,但我不知道为什么,使用计时器会产生不好的代码味道。一定有更好的方法

我可以手动调用验证函数,使视图与模型内联:

 angular.element(document.querySelectorAll('.cb')).scope().checkBoxes()
…让我觉得我是在踏入$digest循环

.
.
以下仅在使用$timeout时有效:

angular.module('app', []).
    controller('testCtrl', function ($scope, $timeout) {
        $scope.guests = [
                            {name:'stephen', lname:'wille'},
                            {name:'mary', lname:'torccaso'}
                        ];
        $scope.form = {};
        $scope.form.cb = {one:false, two:false, three:false, four:false}
        $scope.showRequired = true;

        $scope.checkBoxes = function ()
        {
            console.log('checkbox');
            $scope.showRequired = !($scope.form.cb.one || $scope.form.cb.two ||
                                    $scope.form.cb.three || $scope.form.cb.four);
            $scope.$apply();

        };
        $scope.login = function () {
            console.log('login');
        };

        angular.element(document.querySelectorAll('.cb'))
                .on('click', function () {
                    console.log('click');
                    $scope.checkBoxes();

                /* 
                 * using the $timeout solves the problem, but why?
                 *  
                    $timeout(function () {
                        $scope.checkBoxes();
                    }, 0, false);
                */
                });
    });
$timeout会触发另一个$digest,但$scoope.$apply()也会触发另一个$digest。
那么是什么原因呢


您应该只使用ng click,而不是手动绑定DOM元素上的事件。此外,在控制器中访问DOM也不是一个好的做法。如果您让angular处理这些事件,您就不会遇到这些问题,您还可以安全地删除手动$digest调用($scope.$apply())。也可以使用
ng change
事件而不是
ng click
来正确获取模型值,因为复选框的模型值在更改事件时得到更新

所以基本上你的脚本应该是:-

$scope.handleChange = function(){
    $scope.checkBoxes();
};
$scope.handleChange = function(){
  $scope.showRequired = $scope.form.cb.every(function(itm) {
     return !itm.value;
  });
};
和html:-

    <input class="cb" type="checkbox" value="1" ng-model="form.cb.one"
            ng-required="showRequired" ng-change="handleClick()">one</input>
    <input class="cb" type="checkbox" value="2" ng-model="form.cb.two"
           ng-required="showRequired" ng-change="handleClick()">two</input>
    <input class="cb" type="checkbox" value="3" ng-model="form.cb.three"
           ng-required="showRequired" ng-change="handleClick()">three</input>
    <input class="cb" type="checkbox" value="4" ng-model="form.cb.four"
           ng-required="showRequired" ng-change="handleClick()">four</input>
您可以只删除一个:-

<label ng-repeat="chk in form.cb">
 <input class="cb" type="checkbox" value="{{$index}}" 
      ng-model="chk.value" ng-required="showRequired" 
      ng-change="handleChange()"/> {{chk.text}}</label>
现在这已经足够灵活了,它完全是模型驱动的,并且可以灵活地添加更多的复选框,而无需修改html或逻辑

$scope.handleChange = function(){
  $scope.showRequired = $scope.form.cb.every(function(itm) {
     return !itm.value;
  });
};