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中复制源代码并修改它以处理同步aj​​ax调用,并且默认情况下是同步的。

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”。

要解决此问题,请进行以下修改:

  1. valid变量的声明移到ajax调用和success函数之外,以便进行闭包,并为其指定默认值“pending”。
  2. valid变量的旧声明更改为赋值。
  3. 返回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 }