AngularJS验证ngModel未定义

时间:2016-02-08 17:06:58

标签: angularjs forms validation

我将表单验证动态地添加到表单中,以响应对Web服务的调用。当调用返回时,它会告诉我的验证指令我需要向表单添加哪些验证。 (我这样做是因为我想在提交期间在服务器上重复使用与客户端相同的验证。)当唯一的验证类型为“required”时,这非常有用。 我遇到的问题是当表单控件的模型值没有通过验证规则时,模型值就会被“未定义”。因此,在表单提交时没有任何内容被发送到服务器以在服务器端进行验证。我确实认为如果表单无效,我可以阻止表单提交,但是,我让服务器确定数据的有效性碰到了。

如果模型值违反了验证规则,我该怎么做才能强制模型值为“无效值”?更好的建议?以下是我正在使用的指令的片段。

    //this directive should be put on an ng-form element and it will hide/show any validations set on each input
    .directive('formValidator', ['validatorService', function (vs) {
        return {
            restrict: 'A',
            require: '^form',
            link: function (scope, element, attrs, form) {

                function iterateOverErrorsObject(errors, func, ignorechecking) {
                    if (!func)
                        return;

                    //show any new errors
                    for (var key in errors) {
                        if (key.indexOf('__') == 0)
                            continue;

                        _.each(errors[key], function (obj) {
                            if (form[obj.$name] == obj || ignorechecking) { //ensure the obj is for the current form
                                var input = vs.findElementByName(element, obj.$name);
                                if (input.length > 0) {
                                    func(input, obj);
                                }
                            }
                        });
                    }
                }

                scope.$watch(function () { return form.$error; }, function (newval, oldval, scp) {
                    iterateOverErrorsObject(oldval, function (input, obj) {
                        vs.hideErrors(input);
                    }, true);
                    iterateOverErrorsObject(newval, function (input, obj) {
                        vs.showErrors(input, obj, form._attr);
                    });
                }, true);

                //something told the validator to show it's errors
                scope.$on('show-errors', function (evt) {
                    iterateOverErrorsObject(form.$error, function (input, obj) {
                        vs.showErrors(input, obj, form._attr);
                    });
                });

                scope.$on('hide-errors', function (evt) {
                    vs.hideAllErrors(form);
                });
            }
        };
    }])
    //this directive is to be put on the ng-form element and will dynamically add/remove validators based on the validations configuration
    //which comes back from the service call "Validate"
    .directive('dynamicValidators', ['$compile', function ($compile) {
        return {
            priority: 0,
            restrict: 'A',
            //require: 'ngModel',
            require: '^form',
            scope: {
                'validations': '=',
            },
            link: function (scope, element, attrs, ctrl) {
                (function (form, scp) {

                    // this will hold any information necessary to get the error message displayed
                    // **have to add the form because the ctrl gets recreated every time the form.$error changes
                    function setAttr(ctrl, key, value) {
                        if (!ctrl._attr)
                            ctrl._attr = {};
                        if (!form._attr)
                            from._attr = {};

                        ctrl._attr[key] = value;
                        var obj = form._attr[ctrl.$name] = {};
                        obj[key] = value;
                    };

                    scope.$watch('validations', function (nv, ov) {
                        form._attr = {};
                        //remove old validators
                        if (ov && ov.length > 0) {
                            _.each(ov, function (e) {
                                var fctrl = form[e.MemberNames[0]];
                                if (fctrl && fctrl.$validators) {
                                    delete fctrl.$validators[e.ErrorKey];
                                    //fctrl.$setValidity(e.ErrorKey, true);
                                    fctrl.$validate();
                                }
                            });
                        }

                        //add new validators
                        if (nv && nv.length > 0) {
                            _.each(nv, function (e) {
                                var fctrl = form[e.MemberNames[0]];
                                if (!fctrl)
                                    return;

                                if (e.ErrorKey == 'required') {
                                    setAttr(fctrl, e.ErrorKey, e.ErrorValue);
                                    fctrl.$validators[e.ErrorKey] = function (modelValue, viewValue) {
                                        if (modelValue instanceof Array)
                                            return modelValue.length > 0;
                                        else
                                            return modelValue !== '' && modelValue !== null && modelValue !== undefined;
                                    };
                                } else if (e.ErrorKey == 'alphanumeric') {
                                    setAttr(fctrl, e.ErrorKey, e.ErrorValue);
                                    fctrl.$validators[e.ErrorKey] = function (modelValue, viewValue) {
                                        return viewValue == null || (viewValue != null && /^[a-zA-Z0-9]*$/.test(modelValue));
                                    };
                                } else if (e.ErrorKey == 'min') {
                                    setAttr(fctrl, e.ErrorKey, e.ErrorValue);
                                    fctrl.$validators[e.ErrorKey] = function (modelValue, viewValue) {
                                        return modelValue === undefined || modelValue === null || modelValue === "" || modelValue >= e.ErrorValue;
                                    }
                                } else if (e.ErrorKey == 'max') {
                                    setAttr(fctrl, e.ErrorKey, e.ErrorValue);
                                    fctrl.$validators[e.ErrorKey] = function (modelValue, viewValue) {
                                        return modelValue === undefined || modelValue === null || modelValue === "" || modelValue <= e.ErrorValue;
                                    }
                                }

                                //make the validator fire to set the status of the validator
                                if (fctrl.$validators[e.ErrorKey])
                                    //fctrl.$setValidity(e.ErrorKey, fctrl.$validators[e.ErrorKey](fctrl.$modelValue, fctrl.$viewValue))
                                    fctrl.$validate();
                            });
                        }
                    });
                })(ctrl, scope);
            },
        }
    }]);

1 个答案:

答案 0 :(得分:14)

如果您仍想向服务器发送无效数据,可以将allowInvalid选项与ngModelOptions指令一起使用:

<input type="text" name="userName"
         ng-model="user.name"
         ng-model-options="{ allowInvalid: true }" />

来自ngModelOptions的文档:

  

模型更新和验证

     

ngModel中的默认行为是模型值设置为   验证确定值无效时undefined。通过   将allowInvalid属性设置为true,模型仍然是   即使值无效也会更新。