jqueryvalidation不等待远程validation返回true,认为表单有效
$("#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());
即使值无效,此输出也为true。 我看到validation最终失败并显示错误消息,但表单仍然提交。
从jQuery Validate 1.11.1开始(甚至可能更旧),接受的答案不起作用。 此外,这个问题没有简单的答案,解决方案需要为jQuery Validation添加自定义validation方法。
实际上,简单的答案可能只是:如果您想要做的只是提交表单,请不要手动调用valid()
。 只需让Validate插件为您完成。 在内部,它将等待所有异步请求完成,然后才允许提交表单。 只有在手动检查valid()
或element()
时才会出现此问题。
但是,有很多原因可能导致您需要这样做。 例如,我正在处理的页面需要在启用表单的其余部分之前使用远程validation器检查字段的有效性。 我可以手工完成,而不是使用jQuery Validation,但这是一个重复的工作。
那么,为什么设置async: false
不起作用? 如果将async设置为false, 则会同步进行请求,但插件不能正确处理此请求。 内部remote
函数总是返回"pending"
,这将导致valid()
函数返回true
即使请求已经完成并收到错误响应! 它不会检查响应的值,也不会在以后显示错误。
使用同步回调时使valid()
和element()
同步运行的解决方案是添加自定义validation方法。 我自己试过这个,看起来效果很好。 您可以从常规远程validation中复制源代码并修改它以处理同步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"; }
注意即使ajax调用完成,它总是返回“pending”。
要解决此问题,请进行以下修改:
- 将
valid
变量的声明移到ajax调用和success函数之外,以便进行闭包,并为其指定默认值“pending”。 - 将
valid
变量的旧声明更改为赋值。 - 返回
valid
变量而不是常量“pending”。
这是插件插件的完整代码。 只需将其保存为js文件,并在包含jQueryvalidation后将其包含在页面或模板中:
//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.");
我用自己的forms对此进行了测试,效果很好。 在启用表单的其余部分之前,我可以测试元素的有效性。 但是,您可能希望设置onkeyup: false
以防止在每次按键时执行同步回调。 我也喜欢使用onfocusout: false
。
要使用此function,只需将validation设置中的“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 });
陷入同样的问题似乎你已经设置了对synchronous的远程调用–async:false
否则$("form").valid()
将返回true进行远程validation,请参阅下面我使用的内容
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" } ) } } }, .....
这是我们在项目中提出的解决方案。
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 } }
这利用了$(“#form”)。validate()。pendingRequest每当有远程validation时总是> 0的事实。
注意:这不适用于在远程请求中设置async: true
。
修复此问题的最简单方法(在此处报告: https : //github.com/jzaefferer/jquery-validation/issues/361 )是检查表单是否有效两次:
if (myForm.valid() && myForm.valid()) { ... }
将远程规则设置为async:false
并使用valid()
检查有效性实际上等待调用完成,但不使用它们的返回值。 再次调用valid()
会将它们考虑在内。
有点难看,但它的工作原理。 我正在使用jquery 2.1.0和jquery-validation 1.11.1,BTW。
如果validation返回false,则必须停止浏览器的正常提交。
$("#new_component_form").submit(function() { if ($(this).valid())) { console.log("I'm a valid form!"); } else { console.log("I'm NOT a valid form!"); //Stop the normal submit of the browser return false; } }
我知道这是补丁但我通过检查当前ajax挂起来修复它
我通过$.active
检查当前的ajax调用,如果不是ajax正在运行它会给你0
$('#frmControlFamily #Identifier').valid(); if ($.active == 0) { // my save logic }