Search code examples
javascriptjqueryajaxjquery-validatejquery-forms-plugin

jquery.validate showErrors() triggered multiple times?


In my test program, I use jquery.validate plugin to check user input fields as so:

<script src="js/jquery-1.12.4.min.js"></script>
<script src="js/jquery-form-3.51.min.js"></script>
<script src="js/jquery-validation-1.15.1/jquery.validate.min.js"></script>

<form id="form-profile" method="post">
    <input name="Age" type="text" />
    <input name="Gender" type="text" />
    <button type="submit">submit</button>
</form>

<script>
$(function() {
    setValidateRules();
});

function setValidateRules() {
    $("#form-profile").validate({
        rules: {
            Age: "required",
            Gender: "required"
        },
        messages: {
            Age: "Please fill in age",
            Gender: "Please fill in gender",
        },
        showErrors: function(errorMap, errorList) {
            alert(JSON.stringify(errorMap));
        }
    });
}

$("#form-profile").ajaxForm({
    dataType: "json",
    beforeSubmit: function(arr, $form, options) {
        return $("#form-profile").valid();
    },
    error: function(result) {
        // todo
    },
    success: function(result) {
        // todo
    }
});
</script>

Now my problem is, when I run the page via browser, after clicking submit button, the page keeps popping up alert box recursively, which makes me believe that showErrors() handler is called multiple (many many) times.

Is there a way to solve this problem ?

updated jsfiddle:

https://jsfiddle.net/1nnqf7qs/


Solution

  • jquery.validate showErrors() triggered multiple times?

    It's really not. Using console.log() confirms that each triggering event only fires showErrors() one time. For your demo, default triggering events are click of submit button, and focusout and keyup of each text input.1

    Now my problem is, when I run the page via browser, after clicking submit button, the page keeps popping up alert box recursively, which makes me believe that showErrors() handler is called multiple (many many) times.

    It has to do with how/when alert() halts all JavaScript execution until it's dismissed, and how/when certain browsers handle the alert(). (I've seen Safari get stuck in an infinite loop of alerts where a console.log() in its place would have fired one time.)

    This can be proven by simply replacing your alert() with a console.log() and you can see showErrors is really only fired ONE time per each triggering event.2

    DEMO: jsfiddle.net/1nnqf7qs/1/

    1EDIT: When the alert() is clicked, the field immediately loses focus (focusout event fires), which triggers another alert() that will appear as soon as the first alert() dismisses. Infinite loop. When using console.log(), the field never loses focus so no additional notifications are triggered.

    2EDIT: After initial form validation (after "lazy" turns into "eager" validation), when you click the button, you are then triggering TWO events... focusout and click and the showErrors function responds accordingly by firing twice (once per each of these two different events).

    Is there a way to solve this problem ?

    Do not use an alert() for development and troubleshooting, use console.log() instead.

    See: console.log() versus alert()

    Otherwise, I see no problem with how the showErrors function is being fired.


    You also need to put your Ajax INSIDE the submitHandler function of the .validate() method. As per docs, this is where it belongs.

    $("#form-profile").validate({
        rules: {
            Age: "required",
            Gender: "required"
        },
        messages: {
            Age: "Please fill in age",
            Gender: "Please fill in gender",
        },
        showErrors: function(errorMap, errorList) {
            console.log(JSON.stringify(errorMap));
        },
        submitHandler: function(form) {
            $(form).ajaxForm({
                dataType: "json",
                beforeSubmit: function(arr, $form, options) {
                    // form is ALREADY valid when submitHandler fires
                    // return $("#form-profile").valid(); // <- do NOT need this here
                }, ....
            });
            return false;
        }
    });
    

    Then once inside the submitHandler, you no longer need to check if the form is valid, because the submitHandler only fires when the form is valid.