【问题标题】:jQuery validator and a custom rule that uses AJAXjQuery 验证器和使用 AJAX 的自定义规则
【发布时间】:2011-02-07 09:01:54
【问题描述】:

我阅读了您关于 jQuery 验证器的回复,您在其中概述了一种根据数据库中的值检查用户名的方法。

我尝试过实现此方法,但无论从 PHP 文件返回什么,我总是会收到用户名已被占用的消息。

这是自定义方法...

$.validator.addMethod("uniqueUserName", function(value, element) {
  $.ajax({
      type: "POST",
       url: "php/get_save_status.php",
      data: "checkUsername="+value,
      dataType:"html",
   success: function(msg)
   {
      // if the user exists, it returns a string "true"
      if(msg == "true")
         return false;  // already exists
      return true;      // username is free to use
   }
 })}, "Username is Already Taken");

这是验证代码...

username: {
    required: true,
    uniqueUserName: true
},

是否有一种特定的方式我应该从 php 返回消息。

谢谢

一个

【问题讨论】:

    标签: jquery ajax validation jquery-validate


    【解决方案1】:

    对于其他偶然发现此问题的人,请验证支持“远程”方法,该方法在 2010 年可能不存在:

    https://jqueryvalidation.org/remote-method/

    $("#myform").validate({
      rules: {
        email: {
          required: true,
          email: true,
          remote: {
            url: "check-email.php",
            type: "post",
            data: {
              username: function() {
                return $("#username").val();
              }
            }
          }
        }
      }
    });
    

    【讨论】:

    • 这是发出异步请求还是同步请求?
    • @Raghav,这是一个异步验证
    • 您能告诉我如何延迟这个远程请求吗?
    【解决方案2】:

    您正在执行 AJAX 请求,ergo:当您的自定义验证器返回 true 或 false 时,验证已经完成。

    您需要使用async。另见这篇文章:How can I get jQuery to perform a synchronous, rather than asynchronous, Ajax request?

    类似:

    function myValidator() {
       var isSuccess = false;
    
       $.ajax({ url: "", 
                data: {}, 
                async: false, 
                success: 
                    function(msg) { isSuccess = msg === "true" ? true : false }
              });
        return isSuccess;
    }
    

    警告:

    从 jQuery 1.8 开始,使用 async: false 和 jqXHR ($.Deferred) 是 已弃用;您必须使用成功/错误/完成回调选项 而不是jqXHR对象的相应方法如 jqXHR.done() 或已弃用的 jqXHR.success()。

    【讨论】:

    • 为了让它工作,我不得不将 msg==="true" 更改为 msg===true (Firefox)。顺便感谢您的解决方案!
    • 对于将来遇到此问题的任何人,异步已被弃用。请参阅下面蒂姆的回答。
    • 如果服务器验证需要时间,这将冻结页面。
    • 基于async的贬值:false,我认为这应该不是正确答案
    【解决方案3】:

    我花了很长时间才弄清楚如何将包含页面中元素值的 jsonified 字符串放入远程请求中 - 这是多个小时和尝试多个搜索结果的组合结果。

    重点:

    1. async:false 已被弃用,
    2. remote: 之后的函数调用是使用元素值创建数据字符串的关键。在data: 为字段返回空白值并将dataType 设置为json 之后尝试从表单访问当前值。

          $("#EmailAddress").rules("add", {
          required: true,
          remote: function () { // the function allows the creation of the data string 
                                // outside of the remote call itself, which would not 
                                // return a current value from the form.
              var emailData = "{'address':'" + 
                              $('#SignupForm :input[id$="EmailAddress"]').val() + 
                              "'}";
              var r = {
                  url: "foobar.aspx/IsEmailAvailable",
                  type: "post",
                  dataType: "json",
                  contentType: "application/json; charset=utf-8",
                  cache: false,
                  data: emailData,
                  dataFilter: function(response) {
                      this.email_run = true; //fix for race condition with next button
                      return isAvailable(data); //return true or false
                  }
              };
              return r;
          },
          messages: {
              remote: "* Email in use"
          }
      });
      

    .ASPX 页面:

    <input id="EmailAddress" required name="Email" type="email" placeholder="Email Address*" runat="server"/>
    

    C# 代码背后:

    [WebMethod]
        public static object IsEmailAvailable(string address){...}
    

    格式化响应对象:

    function isAvailable(data) {
        var response = JSON.parse(getJsonObject(data));
        return (response.isAvailable === "True") ? true : false;
    };
    
    //transform response string to a JavaScript Object()
    //http://encosia.com/never-worry-about-asp-net-ajaxs-d-again/ 
    function getJsonObject(data) {
        var msg = eval('(' + data + ')');
        if (msg.hasOwnProperty('d'))
            return msg.d;
        else
            return msg;
    };
    

    【讨论】:

    • 关于您的声明 - 1. async:false has been deprecated,.. 是的,但是如果您使用适当的回调/处理程序,例如(complete:success:error:)而不是一个 Promise 方法,例如 .then.done... 在此处查看以下参考 ==> bugs.jquery.com/ticket/11013#comment:40
    【解决方案4】:

    这是我的“老派”技巧...

    下面是一个实用函数,它允许通过“jquery.validate.js”库使用“异步”验证。此函数会在用户击键之间产生延迟,否则验证函数“validFunc”将被称为“所有时间”,这在某些情况下性能不佳,尤其是在“服务器端”/“后端”上执行验证的函数(基本上是 ajax 调用) )。这样,“validFunc”验证函数仅在用户停止输入一段时间后才被调用,这也允许在用户输入时进行“实时”验证(jqv 设置上的"onkeyup": true)。

    重要提示:涉及使用“jqvAsyncValid”函数的验证应始终放在最后,以避免由于异步而与其他验证发生冲突。

    {
        [...]
        "rules": {
            "field_name": {
                "required": true,
                "maxlength": 12,
                "minlength": 4,
    
                // NOTE: Validation involving the use of the "jqvAsyncValid" function. By Questor
                "my_custom_ajax_validation": true
    
            },
        [...]
    }
    

    答案代码:

    // NOTE: Adds the custom validation "my_custom_ajax_validation". By Questor
    $.validator.addMethod("my_custom_ajax_validation", function (value, element) {
        return jqvAsyncValid(element, "my_custom_ajax_validation", myValidationFunc, this);
    }, "My error message!");
    
    // NOTE: My validation function. By Questor
    function myValidationFunc(domElement) {
        if (someFuncWithAjaxCall(domElement.value) == "ALL_RIGHT!") {
            return true;
        } else {
            return false;
        }
    }
    
    // NOTE: Global "json" variable that stores the "status" ("isValid") and cycle control
    // ("toCtrl") of asynchronously validated elements using the "jqvAsyncValid" function.
    // By Questor
    var jqvAsyncVState = {};
    
    // NOTE: A utility function that allows the use of asynchronous validations with
    // "jquery.validate.js". This function creates a delay between one user keystroke and
    // another otherwise the validation function "validFunc" will be called "all time"
    // which is not very performative in some circumstances and especially problematic
    // for functions that perform validations on the serverside/backend (ajax calls basically).
    // In this way the "validFunc" validation function is only called when the user stops
    // typing for a certain period of time, which also allows a "realtime" validation
    // as it occurs while the user is typing. By Questor
    // [Ref .: https://jqueryvalidation.org/ ]
    //. domElement - DOM element informed by jqv in the "addMethod" for the anonymous
    // function;
    //. asyncRuleNm - Validation name added via "addMethod";
    //. validFunc - Function that will do the validation. Must have the signature
    // "funcName(domElement)" returning "true" for valid and "false" for not;
    //. jQValidInst - Instance of the current jqv within "addMethod". It is usually
    // denoted by "this";
    //. toInMsecs - "Timeout" in "milliseconds". If not informed the default will be
    // 1500 milliseconds. Be careful not to use a very short timeout especially in
    // "ajax" calls so as not to overload the serverside/backend.
    // Eg.: `return jqvAsyncValid(element, "my_custom_ajax_validation", myValidationFunc, this);`.
    function jqvAsyncValid(domElement, asyncRuleNm, validFunc, jQValidInst, toInMsecs) {
        if (typeof toInMsecs === "undefined" || toInMsecs === "") {
            toInMsecs = 1500;
        }
        var domEKey = jQValidInst.currentForm.id + domElement.name;
    
        // NOTE: The validation messages need to be "displayed" and "hidden" manually
        // as they are displayed asynchronously. By Questor
        function errMsgHandler() {
            if (jqvAsyncVState[domEKey]["isValid"]) {
    
                // NOTE: If the current error message displayed on the element was that
                // set in the rule added via "addMethod" then it should be removed since
                // the element is valid. By Questor
                // [Ref.: https://stackoverflow.com/a/11652922/3223785 ,
                // https://stackoverflow.com/a/11952571/3223785 ]
                if (jQValidInst.errorMap[domElement.name] == $.validator.messages[asyncRuleNm]) {
                    var iMsgNow = {};
                    iMsgNow[domElement.name] = "";
                    jQValidInst.showErrors(iMsgNow);
                }
    
            } else {
                var iMsgNow = {};
    
                // NOTE: If the element is invalid, get the message set by "addMethod"
                // for current rule in "$.validator.messages" and show it. By Questor
                iMsgNow[domElement.name] = $.validator.messages[asyncRuleNm];
                jQValidInst.showErrors(iMsgNow);
    
            }
        }
        if (!jqvAsyncVState.hasOwnProperty(domEKey)) {
    
            // NOTE: Set the global json variable "jqvAsyncVState" the control attributes
            // for the element to be asynchronously validated if it has not already been
            // set. The key "domEKey" is formed by the "id" of the "form" that contains
            // the element and the element's "name". By Questor
            jqvAsyncVState[domEKey] = {
                "toCtrl": null,
                "isValid": undefined
            };
    
        }
        var useOnKeyup = true;
    
        // NOTE: The "onblur" event is required for "first validation" that only occurs
        // in a "blur" event - this is inherent to jqv - and for situations where the
        // user types very fast and triggers "tab" and the event "onkeyup" can not deal
        // with it. By Questor
        domElement.onblur = function (e) {
            jqvAsyncVState[domEKey]["isValid"] = validFunc(domElement);
            errMsgHandler();
            useOnKeyup = false;
        }
        if (useOnKeyup) {
    
            // NOTE: The strategy with the event "onkeyup" below was created to create
            // a "delay" between a "keystroke" and another one otherwise the validation
            // function "validFunc" will be called "all time" which is not very performative
            // in some circumstances and especially problematic for functions that perform
            // serverside/backend validations (ajax calls basically). In this way the
            // "validFunc" validation function is only called when the user stops typing
            // for a certain period of time ("toInMsecs"). By Questor
            domElement.onkeyup = function (e) {
    
                // NOTE: Clear the "toCtrl" if it has already been set. This will
                // prevent the previous task from executing if it has been less than
                // "toInMsecs". By Questor
                clearTimeout(jqvAsyncVState[domEKey]["toCtrl"]);
    
                // NOTE: Make a new "toCtrl" set to go off in "toInMsecs" ms. By Questor
                jqvAsyncVState[domEKey]["toCtrl"] = setTimeout(function () {
                    jqvAsyncVState[domEKey]["isValid"] = validFunc(domElement);
                    errMsgHandler();
                }, toInMsecs);
            };
        }
        return jqvAsyncVState[domEKey]["isValid"];
    }
    

    【讨论】:

      猜你喜欢
      • 2016-04-10
      • 2018-03-02
      • 2011-04-10
      • 1970-01-01
      • 1970-01-01
      • 2016-10-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多