ore*_*ake 22 jquery jquery-validate
$("#new_component_form").validate({
errorClass: 'input-error',
rules : {
"comp_data[account_name]" : {
required: true,
remote: {
url: "/validate",
data: {
provider: 'twitter'
}
}
}
},
onsubmit: true,
onfocusout: false,
onkeyup: false,
onclick: false
});
$("#new_component_form").submit(function(){
console.log($(this).valid());
Run Code Online (Sandbox Code Playgroud)
即使值无效,此输出也为true.我看到验证最终失败并显示错误消息,但表单仍然提交.
Gla*_*zed 28
从jQuery Validate 1.11.1开始(甚至可能更旧),接受的答案不起作用.此外,这个问题没有简单的答案,解决方案需要为jQuery Validation添加自定义验证方法.
实际上,简单的答案可能只是:valid()如果你想要做的只是提交表格,不要手动打电话.只需让Validate插件为您完成.在内部,它将等待所有异步请求完成,然后才允许提交表单.只有在您手动检查valid()或时,才会出现此问题element().
但是,有很多原因可能导致您需要这样做.例如,我正在处理的页面需要在启用表单的其余部分之前使用远程验证器检查字段的有效性.我可以手工完成而不是使用jQuery Validation,但这是一个重复的工作.
那么,为什么设置async: false不起作用?如果将async设置为false,则将同步进行请求,但是,插件无法正确处理此请求.内部remote函数总是返回"pending",即使请求已经完成并收到错误响应,也会导致valid()函数返回true !它不会检查响应的值,也不会在以后显示错误.
使用同步回调时制作valid()和执行element()同步的解决方案是添加自定义验证方法.我自己试过这个,看起来效果很好.您可以从常规远程验证中复制源代码并修改它以处理同步ajax调用,并且默认情况下是同步的.
v1.11.1中远程函数的源代码从jquery.validate.js的第1112行开始:
remote: function( value, element, param ) {
if ( this.optional(element) ) {
return "dependency-mismatch";
}
var previous = this.previousValue(element);
if (!this.settings.messages[element.name] ) {
this.settings.messages[element.name] = {};
}
previous.originalMessage = this.settings.messages[element.name].remote;
this.settings.messages[element.name].remote = previous.message;
param = typeof param === "string" && {url:param} || param;
if ( previous.old === value ) {
return previous.valid;
}
previous.old = value;
var validator = this;
this.startRequest(element);
var data = {};
data[element.name] = value;
$.ajax($.extend(true, {
url: param,
mode: "abort",
port: "validate" + element.name,
dataType: "json",
data: data,
success: function( response ) {
validator.settings.messages[element.name].remote = previous.originalMessage;
var valid = response === true || response === "true";
if ( valid ) {
var submitted = validator.formSubmitted;
validator.prepareElement(element);
validator.formSubmitted = submitted;
validator.successList.push(element);
delete validator.invalid[element.name];
validator.showErrors();
} else {
var errors = {};
var message = response || validator.defaultMessage( element, "remote" );
errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message;
validator.invalid[element.name] = true;
validator.showErrors(errors);
}
previous.valid = valid;
validator.stopRequest(element, valid);
}
}, param));
return "pending";
}
Run Code Online (Sandbox Code Playgroud)
注意即使ajax调用完成,它总是返回"pending".
要解决此问题,请进行以下修改:
valid变量的声明移到ajax调用和success函数之外,以便进行闭包,并为其指定默认值"pending".valid变量的旧声明更改为赋值.valid变量而不是常量"pending".这是插件插件的完整代码.只需将其保存为js文件,并在包含jQuery验证后将其包含在页面或模板中:
//Created for jQuery Validation 1.11.1
$.validator.addMethod("synchronousRemote", function (value, element, param) {
if (this.optional(element)) {
return "dependency-mismatch";
}
var previous = this.previousValue(element);
if (!this.settings.messages[element.name]) {
this.settings.messages[element.name] = {};
}
previous.originalMessage = this.settings.messages[element.name].remote;
this.settings.messages[element.name].remote = previous.message;
param = typeof param === "string" && { url: param } || param;
if (previous.old === value) {
return previous.valid;
}
previous.old = value;
var validator = this;
this.startRequest(element);
var data = {};
data[element.name] = value;
var valid = "pending";
$.ajax($.extend(true, {
url: param,
async: false,
mode: "abort",
port: "validate" + element.name,
dataType: "json",
data: data,
success: function (response) {
validator.settings.messages[element.name].remote = previous.originalMessage;
valid = response === true || response === "true";
if (valid) {
var submitted = validator.formSubmitted;
validator.prepareElement(element);
validator.formSubmitted = submitted;
validator.successList.push(element);
delete validator.invalid[element.name];
validator.showErrors();
} else {
var errors = {};
var message = response || validator.defaultMessage(element, "remote");
errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message;
validator.invalid[element.name] = true;
validator.showErrors(errors);
}
previous.valid = valid;
validator.stopRequest(element, valid);
}
}, param));
return valid;
}, "Please fix this field.");
Run Code Online (Sandbox Code Playgroud)
我用自己的形式对此进行了测试,效果很好.在启用表单的其余部分之前,我可以测试元素的有效性.但是,您可能希望设置onkeyup: false为阻止在每次按键时执行同步回调.我也喜欢用onfocusout: false.
要使用此功能,只需将验证设置中的"remote"替换为您想要使用它的"synchronousRemote".例如:
$("#someForm").validate({
rules: {
someField: {
required: true,
synchronousRemote: {
url: "/SomePath/ValidateSomeField"
//notice that async: false need not be specified. It's the default.
}
}
},
messages: {
someField: {
required: "SomeField is required.",
synchronousRemote: "SomeField does not exist."
}
},
onkeyup: false,
onfocusout: false
});
Run Code Online (Sandbox Code Playgroud)
陷入同样的问题似乎你已经设置了对synchronous的远程调用 - async:false
否则,$("form").valid()对于远程验证,将返回true,请参阅下面的内容
rules: {
NameToValidate: {
required: true,
remote: function()
{
return {
type: "POST",
async: false,
url: "www.mysite.com/JSONStuff",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify( {
Name: "UNIQUE NAME"
} )
}
}
},
.....
Run Code Online (Sandbox Code Playgroud)
解决此问题的最简单方法(在此处报告:https://github.com/jzaefferer/jquery-validation/issues/361)是检查表单是否有效两次:
if (myForm.valid() && myForm.valid()) {
...
}
Run Code Online (Sandbox Code Playgroud)
async:false使用valid()实际等待调用完成来设置远程规则并检查有效性,但不使用它们的返回值.valid()再次呼叫将它们考虑在内.
有点难看,但它的工作原理.我正在使用jquery 2.1.0和jquery-validation 1.11.1,BTW.
这是我们在项目中提出的解决方案.
var validPendingTimeout;
function doSomethingWithValid() {
var isValid = $("#form").valid();
var isPending = $("#form").validate().pendingRequest !== 0;
if (isPending) {
if (typeof validPendingTimeout !== "undefined") {
clearTimeout(validPendingTimeout);
}
validPendingTimeout = setTimeout(doSomethingWithValid, 200);
}
if (isValid && !isPending) {
// do something when valid and not pending
} else {
// do something else when not valid or pending
}
}
Run Code Online (Sandbox Code Playgroud)
这利用了$("#form").validate().pendingRequest在远程验证时总是> 0的事实.
注意:这不适async: true用于远程请求中的设置.
我通过创建一个自定义函数来检查$("#form").valid()和解决这个问题$("#form").validate().pendingRequest:
function formIsValid() {
return $("#form").valid() && $("#form").validate().pendingRequest === 0;
}
Run Code Online (Sandbox Code Playgroud)
这适用于$("#form").validate().pendingRequest在remote验证请求期间始终 > 0的假设。这使用 jquery-validation 1.19.1 工作。