jQuery 验证:使用 AJAX 的自定义验证器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16993166/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 18:14:20  来源:igfitidea点击:

jQuery Validation: Custom validator with AJAX

jqueryajaxvalidation

提问by Spanky

OK, I give up. After trying endless permutations of inline functions, callbacks, return parameters, I still cannot get this to behave how I want. Any help would be appreciated.

好吧,我放弃了。在尝试了无数种内联函数、回调、返回参数的排列之后,我仍然无法让它按照我想要的方式运行。任何帮助,将不胜感激。

Current status: everything works except the 'checkEmail' error message. The javascript popups convey the proper messages to the user, but the field will not show any error message, whether true or false is returned by the handlers.

当前状态:除“checkEmail”错误消息外,一切正常。javascript 弹出窗口向用户传达正确的消息,但该字段不会显示任何错误消息,无论处理程序返回 true 还是 false。

The desired outcome is that if the JSON payload from the AJAX call is anything other than a 200, to pop a Javascript alert and highlight the field as invalid with the appropriate error message. Currently, it pops the alerts, but doesn't mark the field as invalid.

期望的结果是,如果来自 AJAX 调用的 JSON 负载不是 200,则弹出 Javascript 警报并使用适当的错误消息将该字段突出显示为无效。目前,它会弹出警报,但不会将该字段标记为无效。

(Sorry, this is jQuery 1.7 + jquery.validation plugin)

(抱歉,这是 jQuery 1.7 + jquery.validation 插件)

JSON responses:

JSON 响应:

Our JSON response payloads look like this:

我们的 JSON 响应负载如下所示:

{"message": "Email is not in use.", "code": 200, "email": "[email protected]"}

or

或者

{"message": "Duplicate email address detected", "code": 401}

The code

编码

<html>

<head>
<script>

// You'd think this should be false, but no
// Also it apparently needs to be a quoted 
// string: http://stackoverflow.com/a/11496502/814669
var checkEmailStatus = "true";

// Success Handling
checkEmailSuccess = function(data, textStatus, jqXHR) {
    checkEmailStatus = "true";
    switch (data.code) {
        case 200:
            checkEmailStatus = "false"; // Nothing set here matters
            return false; // Return valued from here don't matter
        case 401:
            alert("Sorry, our system has detected that an account with this email address already exists.");
            break;
        case undefined:
            alert("An undefined error occurred.");
            break;
        default:
            alert("An undefined error occurred.");
            break;
    }
    return checkEmailStatus;
};


// Error Handling
checkEmailError = function(jqXHR, textStatus, errorThrown) {
    if (jqXHR.status == 404) {
        alert("Could not find the API Server (404). We apologize for the inconvenience.");
    } else {
        alert("Terrible things have happened" + textStatus);
    }
    return false;
};


// The Validator
jQuery.validator.addMethod("checkEmail", function(value, element) {

    $.ajax({
        type: "POST",
        cache: "false",
        async: "false",
        url: "/json/checkEmail",
        dataType: "json",
        data: {
            email: function() {
                return $("email").val();
            }
        },
        success: checkEmailSuccess,
        error: checkEmailError
    });

    // Seems checkEmailStatus value never gets changed:
    return checkEmailStatus;

}, "Email Address Problem");


// The Binding
$(document).ready(function(){
    $('#MyForm').validate({
        onfocusout: false,
        onkeyup: false,
        rules: {
            "email": {
                required: true,
                minlength: 2,
                maxlength: 42,
                email: true,
                checkEmail: true
            }
        }
    });
});

</script>
</head>

<body>

    <!-- the Form -->
    <form id="MyForm">
        <input type="text" name="email"/>
        <input type="submit" name="submit"/>
    </form>

</body>
</html>

回答by Spanky

The correct answer here is to indeed use the "remote" option, but do all of your response processing using "dataFilter":

这里的正确答案是确实使用“remote”选项,但使用“dataFilter”完成所有响应处理:

checkEmailSuccess = function(response) {
    switch (jQuery.parseJSON(response).code) {
        case 200:
            return "true"; // <-- the quotes are important!
        case 401:
            alert("Sorry, our system has detected that an account with this email address already exists.");
            break;
        case undefined:
            alert("An undefined error occurred.");
            break;
        default:
            alert("An undefined error occurred");
            break;
    }
    return false;
};

"email": {
    required: true,
    minlength: 2,
    maxlength: 42,
    email: true,
    remote: {
        url: "/json/checkEmail",
        type: "POST",
        cache: false,
        dataType: "json",
        data: {
            email: function() { return $("#email").val(); }
        },
        dataFilter: function(response) {
            return checkEmailSuccess(response);
        }
    }
},

回答by epignosisx

The addMethod expects a true/false response inmediately and you are doing an AJAX call which is an async operation so the variable checkEmailStatus will return its initial value. Please look into "remote" validation, this is what you need:

addMethod 期望立即获得真/假响应,并且您正在执行 AJAX 调用,这是一个异步操作,因此变量 checkEmailStatus 将返回其初始值。请查看“远程”验证,这是您需要的:

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

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

Update: I just noticed the async = false. Try to avoid that option. It reduces the user experience.

更新:我刚刚注意到 async = false。尽量避免这种选择。它降低了用户体验。

Try this:

尝试这个:

$('#MyForm').validate({
    onfocusout: false,
    onkeyup: false,
    rules: {
        "email": {
            required: true,
            minlength: 2,
            maxlength: 42,
            email: true,
            //checkEmail: true
            remote:{
                url: "/json/checkEmail", //make sure to return true or false with a 200 status code
                type: "post",
                data: {
                    email: function() {
                        return $("email").val();
                    }
                }
            }
        }
    }
});

回答by bblue

If you want to use actual http response codes, you can use the error function of the $.ajax call, it will work inside the validation plugin.

如果你想使用实际的 http 响应代码,你可以使用 $.ajax 调用的错误函数,它会在验证插件中工作。

remote: {
    url: "/json/checkEmail",
    type: "POST",
    cache: false,
    dataType: "json",
    data: {
        email: function() { return $("#email").val(); }
    },
    error: function(jqXHR, textStatus, errorThrown) {
        alert(jqXHR.status);
        alert(textStatus);
        alert(errorThrown);
    }