AngularJS复选框和$验证器

时间:2014-09-23 15:24:33

标签: angularjs

我有一个由ID数组支持的复选框列表。

<input type="checkbox" name="checkers" value="black" ng-model="board" />
<input type="checkbox" name="checkers" value="white" ng-model="board" />

该模型看起来像:

 [ 'black', 'white' ]

因此,有许多“黑客”可以让人们按照自己的想法行事,甚至是指令checklist-model

我的问题是我有一个使用ngModelController的$validators进行动态验证的指令。该指令看起来像这样:

module.directive('validator', function($parse) {
    return {
        restrict: 'A',
        require: '?ngModel',
        link: function($scope, $element, $attrs, ngModelCtrl) {
            var rules = $parse($attrs.validator)($scope);
            ngModelCtrl.$validators.myValidator = function(val){

                // this is simplified, real case is much more complex
                if(rules.minSelections > 0){
                    return !(val.length <= rules.minSelections);
                }

                if(rules.required){
                    return !val.length;
                }

            }
        }
    }
});

我将它附在我的复选框上,如:

<input type="checkbox" name="checkers" val="black" validators="{ minSelections: 1 }" ng-model="board" />
<input type="checkbox" name="checkers" val="white" validators="{ minSelections: 1 }" ng-model="board" />

问题是val验证中的myValidator始终返回true / false。尽管采用了几种不同的方法甚至使用该指令,我似乎无法看到我需要的“实际”模型。注意:$ validators在点击该指令之前运行。

有人有任何建议吗?

1 个答案:

答案 0 :(得分:0)

我最终创建了自己的checkbox指令并手动触发验证。

如果您查看下面的内容,您可以看到我如何观看该集合,如果值已更改,我提交值并手动重新触发验证。

继承人的代码:

define(['angular'], function (angular) {

    // Use to style checkboxes, bind checkboxes to arrays, and run validators on checkboxes
    // Modified from: https://github.com/bkuhl/angular-form-ui/tree/master/src/directives/checkBox
    var module = angular.module('components.checkbox', []);

    /**
     * <check-box ng-model="isChecked()"></check-box>
     * Required attribute: ng-model="[expression]"
     * Optional attribute: value="[expression]"
     */
    module.directive('checkBox', function () {
        return {
            replace: true,
            restrict: 'E',
            scope: {
                'externalValue': '=ngModel',
                'value': '&'
            },
            require: 'ngModel',
            template: function (el, attrs) {
                var html = '<div class="ngCheckBox' + ((angular.isDefined(attrs.class)) ? ' class="'+attrs.class+'"' : '') + '">'+
                    '<span ng-class="{checked: isChecked}">' +
                        '<input type="checkbox" ng-model="isChecked"' + ((angular.isDefined(attrs.id)) ? ' id="'+attrs.id+'"' : '') + '' + ((angular.isDefined(attrs.name)) ? ' name="'+attrs.name+'"' : '') + '' + ((angular.isDefined(attrs.required)) ? ' name="'+attrs.required+'"' : '') + '/>'+
                    '</span>'+
                '</div>';
                return html;
            },
            controller: function ($scope) {
                if (angular.isArray($scope.externalValue)) {
                    $scope.isChecked = $scope.externalValue.indexOf($scope.value()) >= 0;
                } else {
                    $scope.isChecked = !!$scope.externalValue;
                }

                $scope.$watch('isChecked', function (newValue, oldValue) {
                    if (angular.isDefined(newValue) && angular.isDefined(oldValue)) {
                        //add or remove items if this is an array
                        if (angular.isArray($scope.externalValue)) {
                            var index = $scope.externalValue.indexOf($scope.value());
                            if(newValue) {
                                if( index < 0 ) $scope.externalValue.push($scope.value());
                            } else {
                                if( index >= 0 ) $scope.externalValue.splice(index, 1);
                            }
                        } else {
                            //simple boolean value
                            $scope.externalValue = newValue;
                        }
                    }
                });
            },
            link: function ($scope, $elm, $attrs, ngModel) {
                $scope.$watchCollection('externalValue', function(newVal) {
                    if (newVal.length) {
                        ngModel.$setTouched();
                        ngModel.$commitViewValue();
                        ngModel.$validate();
                    }
                });
            }
        };
    });

    return module;
});