【发布时间】:2016-02-08 17:06:57
【问题描述】:
我将表单验证从对 Web 服务调用的响应中动态添加到表单中。当调用返回时,它会告诉我的验证指令我需要向表单添加哪些验证。 (我这样做是因为我想在提交期间在服务器上重用相同的验证,就像我在客户端上所做的那样。)当唯一的验证是“必需”类型时,这非常有效。 我遇到的问题是当表单控件的模型值没有通过验证规则时,模型值就是“未定义”。因此,在提交表单时不会将任何内容发送到服务器以在服务器端进行验证。我确实意识到如果表单无效,我可以阻止表单提交,但是,我让服务器确定数据的有效性遇到了。
我可以做些什么来强制模型值成为“无效值”,无论它是否违反了验证规则?更好的建议?下面是我正在使用的指令的片段。
//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);
},
}
}]);
【问题讨论】:
-
我不知道你所说的“强制模型值是'无效值'”是什么意思——但如果你在客户端和服务器上使用相同的验证规则,那么发送发送到服务器的无效表单是在浪费用户的时间。如果客户端验证失败,只需阻止提交即可。
-
(我意识到你说过你意识到你可以做到这一点,但是“让服务器确定所遇到数据的有效性”——但如果是这样的话,为什么还要在全部?)
-
例子是这样的。输入必须是字母数字,但不是必需的。输入中的值“12-1”,如果在输入上设置了仅验证字母和数字,则模型值将是“未定义”(因为其中包含“-”)。客户端上的 $viewValue 仍将显示值“12-1”,尽管提交会发送“未定义”。有问题。服务器会说......哦,没有设置,所以当客户端说“12-1”无效并将输入模型设置为未定义时,它不是无效的。 --是的,我可以在客户端检查,但我必须在服务器端做同样的事情。
-
据我所知,答案是“所以不要那样做”。如果您要进行足够的客户端验证来更改模型值,那么就一直这样做,并让用户有机会在提交之前纠正错误。如果您不打算这样做,那么根本不要进行客户端验证,因为它对您或用户没有任何好处。
标签: angularjs forms validation