多个Angular验证器独立工作,但不能一起工作

时间:2013-10-18 23:35:28

标签: javascript validation angularjs

我写了两个验证指令。每个都可以单独工作,但是当两者都应用时,numberValidator会在任何时候失败.Validator失败(因此,因为“3”无法执行rangeValidator,它也会失败numberValidator,即使它在rangeValidator不在图片中时也会失败)。

日志记录验证numberValidator确实失败了(与HTML中的某些错误相比)。

我原本希望这些指令能够彼此独立运行 - 我不希望用户输入“3”并仍然看到“必须是一个数字。”

使用数字输入不是一种选择。

我的JS:

app.directive('rangeValidator', function () {
    return {
        require: 'ngModel',
        link: function (scope, elm, attrs, ctrl) {
            var min = scope.$eval(attrs.minValue);
            var max = scope.$eval(attrs.maxValue);
            ctrl.$parsers.unshift(function (viewValue) {
                if (parseInt(viewValue) >= min && parseInt(viewValue) <= max) {
                    // it is valid
                    ctrl.$setValidity('rangeValidator', true);
                    return viewValue;
                } else {
                    // it is invalid, return undefined (no model update)
                    ctrl.$setValidity('rangeValidator', false);
                    return undefined;
                }
            });
        }
    };
});


app.directive('numberValidator', function () {
    return {
        require: 'ngModel',
        link: function (scope, elm, attrs, ctrl) {
            ctrl.$parsers.unshift(function (viewValue) {
                if (!isNaN(parseInt(viewValue))) {
                    // it is valid
                    console.log('Number Validator passed!');
                    ctrl.$setValidity('numberValidator', true);
                    return viewValue;
                } else {
                    // it is invalid, return undefined (no model update)
                    ctrl.$setValidity('numberValidator', false);
                    return undefined;
                }
            });
        }
    };
});

1 个答案:

答案 0 :(得分:2)

我看到你已经遵循了Angular docs的建议,并在解析器函数中返回了undefined的无效值。这样做(在你的情况下)的问题是它破坏了解析器管道:首先检测到无效值的指令会将undefined传递给下一个,这显然也会认为它无效。

我可以想到两个解决方案:

1)让原始值流过解析器管道:

ctrl.$parsers.unshift(function (viewValue) {
    if (parseInt(viewValue) >= min && parseInt(viewValue) <= max) {
        ctrl.$setValidity('rangeValidator', true);
    } else {
        ctrl.$setValidity('rangeValidator', false);
    }
    return viewValue;
});

...

ctrl.$parsers.unshift(function (viewValue) {
    if (!isNaN(parseInt(viewValue))) {
        ctrl.$setValidity('numberValidator', true);
    } else {    
        ctrl.$setValidity('numberValidator', false);
    }
    return viewValue;
});

工作演示here

这不会阻止使用无效值更新模型,并且您需要使用$valid$invalid属性在使用其值之前检查字段状态,但是您'能够彼此独立地检查错误。

2)为两个指令设置不同的优先级

您可以通过为每个指令设置不同的优先级来控制指令的执行顺序,通过这样做,您可以以增量方式检查无效值,如下所示:

<span ng-show="form.value.$error.rangeValidator">Invalid range</span>
<span ng-show="!form.value.$error.rangeValidator && form.value.$error.numberValidator">Invalid number</span>

工作演示here

它附带一个警告:随着更多验证的增加,它可能会变得非常混乱。

就个人而言,我更喜欢第一种方法,即使它不会阻止模型使用无效值进行更新。