web-dev-qa-db-ja.com

jQueryバリデータとAJAXを使用するカスタムルール

データベース内の値に対してユーザー名をチェックする方法を概説する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からメッセージを返すことになっている特定の方法はありますか?.

ありがとう

A

49
thatweblook

AJAX request、ergo:カスタムバリデータがtrueまたはfalseを返すとき、検証はすでに動作を終了しています。

asyncを使用する必要があります。この記事も参照してください: 非同期ではなく同期のAjaxリクエストをjQueryで実行するにはどうすればよいですか?

何かのようなもの:

function myValidator() {
   var isSuccess = false;

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

警告:

JQuery 1.8では、jqXHR($ .Deferred)でのasync:falseの使用は非推奨です。 jqXHR.done()や非推奨のjqXHR.success()などのjqXHRオブジェクトの対応するメソッドの代わりに、成功/エラー/完全なコールバックオプションを使用する必要があります。

60
Jan Jongboom

これにつまずく人のために、validateは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();
          }
        }
      }
    }
  }
});
62
Tim

ページ内の要素の値を含むjson化された文字列をリモートリクエストに取得する方法を見つけるのに永遠に時間がかかりました。これは、多くの時間と多くの検索結果の組み合わせの結果です。

キーポイント:

  1. async:falseは廃止されました。
  2. remote:の直後の関数呼び出しは、要素の値でデータ文字列を作成するためのキーです。 data:がjsonとしてdataTypeを設定したフィールドに空の値を返した後に、フォームから現在の値にアクセスしようとしています。

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

これが私の「古い学校」ハックです...

「jquery.validate.js」ライブラリで「非同期」検証を使用できるユーティリティ関数の下。この関数は、ユーザーのキーストローク間の遅延を作成します。そうしないと、検証関数「validFunc」は「常時」と呼ばれます。 )。このようにして、「validFunc」検証関数は、ユーザーが一定時間入力を停止したときにのみ呼び出され、「リアルタイム」検証("onkeyup": true(jqv設定で)ユーザーが入力しているときに発生します。

重要:「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"];
}
0
Eduardo Lucio