0

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/

Sparky
  • 98,165
  • 25
  • 199
  • 285
ineztia
  • 815
  • 1
  • 13
  • 29
  • 2
    Just as general advice, try using `console.log("stuff")` rather than alert with debugging, then keeping your console open to view them (f12 on windows). Makes it much easier to see whats going on, as console logs dont get in your way like alerts do - especially if there are a lot of em – Carl Sep 26 '16 at 14:09
  • Where is your submit event in jquery ? – Mohit Tanwani Sep 26 '16 at 14:11
  • I've tried to use console.log, and it seem that console.log() runs 3 times on every call (page load). That's also a strange result, I don't know why alert() is triggered recursively and log only triggered 3 times @Carl – ineztia Sep 26 '16 at 14:14
  • @Loading.. $("#form-profile").ajaxForm(...) is the submit handler, i use ajaxForm plugin – ineztia Sep 26 '16 at 14:16
  • Can you create jsfiddle ? – Mohit Tanwani Sep 26 '16 at 14:16
  • Can you take your ajaxForm code inside document.ready event. – Mohit Tanwani Sep 26 '16 at 14:18
  • @Loading.. jsfiddle added, please check my update – ineztia Sep 26 '16 at 14:37
  • [Your jsFiddle](https://jsfiddle.net/1nnqf7qs/) does not contain the jQuery Library or the jQuery Validate plugin – Sparky Sep 26 '16 at 14:42

2 Answers2

2

I think you need to use

onfocusout: false

Alert always fire because focus out always fire for alert.

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

API refernce : https://jqueryvalidation.org/validate

Sanka
  • 1,294
  • 1
  • 11
  • 20
1

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.

Community
  • 1
  • 1
Sparky
  • 98,165
  • 25
  • 199
  • 285
  • Thanks for detailed explanation. The only problem is that when I run test with console.log(), it actually logs 2 times in chrome inspect window: `demo.html:76 {"Age":"Please fill in age"}`, `demo.html:76 {"Age":"Please fill in age","Gender":"Please fill in gender"}`, it seems that showError() handler will be triggered by every single error in page – ineztia Sep 26 '16 at 16:02
  • @ineztia, I am only seeing `showErrors()` triggered once for each `keyup`, once for each `focusout`, and once when I click the button. Otherwise, how else would you get an immediate and accurate accounting of errors? So I don't understand why this is a problem for you. – Sparky Sep 26 '16 at 16:05
  • @ineztia, of course it's triggered for every single error on the page... otherwise, it would continue to show errors after the user fixes them or not show errors at all. – Sparky Sep 26 '16 at 16:06
  • So how does disabling the `onfocuout` triggering event solve anything? What was the real problem with how this works in the first place? – Sparky Sep 26 '16 at 16:40
  • @Sparky In my test, after submit, the console.log() may fire 2 times as there're 2 error fields (Age and Gender) in page. Chrome inspect window will only show the first log explicitly and collapse other log rows by default, when you click on the log, it will expand the hidden log rows. I don't know if you mean firing 2 times is correct for the validation mechanism. – ineztia Sep 26 '16 at 16:42
  • @ineztia, again, what is the real problem here... you don't really want to use `alert()` boxes in production, do you? As far as `showErrors` firing for each field... of course that's correct as how else do you expect the function to correctly report errors as they dynamically toggle. If you're merely looking for an explanation, see my last edit as I've fully provided that. – Sparky Sep 26 '16 at 16:51
  • @ineztia, also don't forget that after initial form validation (after "lazy" turns into "eager"), when you click the submit, you are triggering TWO events... `focusout` and `click`. – Sparky Sep 26 '16 at 17:14