jQuery验证不等待远程验证返回true,认为表单有效 [英] jquery validation not waiting for remote validation to return true, considers form valid

查看:86
本文介绍了jQuery验证不等待远程验证返回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.我看到验证最终失败,并显示错误消息,但表单仍在提交.

This outputs true, even if the value is invalid. I see the validation eventually fail and show the error message but the form is still submitted.

推荐答案

从jQuery Validate 1.11.1(甚至可能更旧)开始,可接受的答案不起作用.另外,这个问题没有简单的答案,解决方案要求向jQuery验证中添加自定义验证方法.

As of jQuery Validate 1.11.1 (and perhaps even older), the accepted answer does not work. In addition, there is no easy answer to this question, and the solution requires adding a custom validation method to jQuery Validation.

实际上,简单的答案可能是:如果您只想提交表单,请不要手动调用valid().只需让Validate插件为您完成即可.在内部,它将在允许提交表单之前等待所有异步请求完成.仅当您手动检查valid()element()时,才会出现此问题.

Actually, the easy answer may just be: Don't call valid() manually if all you want to do is submit the form. Just let the Validate plugin do it for you. Internally, it will wait for all asynchronous requests to complete before allowing the form to be submitted. This issue only arises when you are manually checking valid() or element().

但是,有很多原因可能导致您需要这样做.例如,我正在处理的页面需要在启用表单的其余部分之前使用远程验证器检查字段的有效性.我可以手动完成此操作,而无需使用jQuery验证,但这是重复的工作.

However, there are plenty of reasons why you may need to do that. For instance, the page I am working on needs to check the validity of a field using a remote validator before enabling the rest of the form. I could just do it by hand instead of using jQuery Validation, but that's a duplication of effort.

那么,为什么设置async: false无效?如果将async设置为false,则请求 将同步发出,但是,插件无法正确处理此请求.内部的remote函数始终返回"pending",这将导致valid()函数返回true ,即使请求已经完成并收到错误的响应!也不检查响应值或直到以后显示错误.

So, why does setting async: false not work? If you set async to false, the request will be made synchronously, however, the plugin doesn't handle this correctly. The internal remote function always returns "pending" which will cause the valid() function to return true even if the request is already complete and received a false response! It doesn't check the value of the response or show the error until later.

使用同步回调时,使valid()element()同步运行的解决方案是添加自定义验证方法.我自己尝试过,看来效果很好.您可以仅从常规远程验证中复制源代码,然后对其进行修改以处理同步aj​​ax调用,并且默认情况下是同步的.

The solution to making valid() and element() behave synchronously when using a synchronous callback is to add a custom validation method. I've tried this myself, and it seems to work fine. You can just copy the source code from the regular remote validation and modify it to handle synchronous ajax calls, and be synchronous by default.

v1.11.1中的远程功能的源代码从jquery.validate.js的第1112行开始:

The source code of of the remote function in v1.11.1 starts on line 1112 of jquery.validate.js:

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调用完成,它也始终会返回待处理"状态.

Notice how it always returns "pending" even if the ajax call is complete.

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

To fix this issue, make the following modifications:

  1. valid变量的声明移至ajax调用和成功函数之外,以进行关闭,并为其指定默认值"pending".
  2. valid变量的旧声明更改为赋值.
  3. 返回valid变量,而不是常量"pending".
  1. Move the declaration of the valid variable outside of the ajax call and the success function in order to make a closure, and assign it a default value of "pending".
  2. Change the old declaration of the valid variable to an assignment.
  3. Return the valid variable instead of the constant "pending".

这是该插件的完整代码.只需将其另存为js文件,并在包含jQuery验证后将其包含在您的页面或模板中即可.

Here's the complete code for a plugin to the plugin. Just save this as a js file and include it in your page or template after the include for jQuery Validation:

//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.");

我已经用自己的表格对其进行了测试,并且效果很好.在启用表单的其余部分之前,我可以测试元素的有效性.但是,您可能希望设置onkeyup: false以防止在每次按键时执行同步回调.我也喜欢使用onfocusout: false.

I've tested this with my own form and it works great. I can test my element for validity before enabling the rest of the form. However, you probably want to set onkeyup: false to prevent performing a synchronous callback on every key press. I also like to use onfocusout: false.

要使用此功能,只需在要使用此功能的任何地方用"synchronousRemote"替换验证设置中的"remote"即可.例如:

To use this, just replace "remote" in your validation settings with "synchronousRemote" everywhere you'd like to use this. For example:

$("#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
});

这篇关于jQuery验证不等待远程验证返回true,认为表单有效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆