1

这组复选框需要至少选中一个才能启用提交按钮。
取消选择所有复选框会禁用该按钮。
所有复选框都使用相同的范围属性 (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() 也会触发。
那么给了什么?

Plunker 示例

4

1 回答 1

2

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

所以基本上你的脚本只是: -

$scope.handleChange = function(){
    $scope.checkBoxes();
};

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

演示

您实际上可以通过使用 ng-repeat 来进一步改进这一点。

如果您在数组中重新排列复选框:-

$scope.form.cb = [{text:'one', value:false}, {text:'two', value:false}, {text:'three', value:false}, {text:'four', value:false}];

你可以只用一个:-

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

脚本将是:-

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

现在这已经足够灵活了,它完全是模型驱动的,并且足够灵活,可以在不修改 html 或逻辑的情况下添加更多复选框。

演示2

Array.prototype.every shim 支持旧版浏览器

于 2014-08-22T02:52:00.677 回答