jquery验证不等待远程验证返回true,认为表单有效

问题描述 投票:22回答:8
$("#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。我看到验证最终失败,并显示错误消息,但表单仍然提交。

jquery jquery-validate
8个回答
28
投票

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

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

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

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

使用同步回调时使valid()element()同步运行的解决方案是添加自定义验证方法。我自己尝试过此方法,看来效果很好。您可以只从常规远程验证中复制源代码,然后对其进行修改以处理同步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调用和成功函数之外,以进行关闭,并为其指定默认值“ pending”。
  2. valid变量的旧声明更改为赋值。
  3. 返回valid变量,而不是常量“ pending”。
  4. 以下是该插件的完整代码。只需将其另存为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.");

我已经用自己的表格进行了测试,效果很好。在启用表单的其余部分之前,我可以测试元素的有效性。但是,您可能需要设置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
});

7
投票

遇到同样的问题,您似乎已将远程调用设置为同步-async:false


6
投票

解决此问题的最简单方法(在此处报告:https://github.com/jzaefferer/jquery-validation/issues/361)是检查表单是否有效两次:


6
投票

这是我们在我的项目中提出的解决方案。


0
投票

[如果验证返回false,则必须停止正常浏览器的提交。


0
投票

我知道这是补丁,但我通过检查当前的ajax是否已解决来修复它]

我通过$.active检查当前的ajax调用,如果没有运行ajax,它将给您0


0
投票

您可以两次验证表单,或者检查当前的ajax调用是否完成。


0
投票

我通过创建一个同时检查$("#form").valid()$("#form").validate().pendingRequest的自定义函数解决了此问题:

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.