jqueryjquery-validatejquery-steps

jQuery Steps stop next step if the input is not valid


I have a simple form with jquery steps and jquery validate.

I have a lot of field with specific format (example: only accepting one of these numbers /^(6|8|10|12)$/).

I'm using regex to check input format so that user know there is something wrong. For the moment, the wrong format just take the red color but by pressing next, the user can go to the next step.

Now I want to forbid next step if the input is not on the right format.

Here is the pen to illustrate the form https://codepen.io/zounars/pen/MZYxKB

<!-- Thanks to Pieter B. for helping out with the logistics -->
<div class="container">
<form id="contact" action="#">
<div>
    <h3>Account</h3>
    <section>
        <label for="userName">User name *</label>
        <input id="userName" name="userName" type="text" class="required">
        <label for="specialNumber">Special number *</label>
        <input id="specialNumber" name="specialNumber" type="text" class="required">
        <p>(*) Mandatory</p>
    </section>

    <h3>Profile</h3>
    <section>
        <label for="name">First name *</label>
        <input id="name" name="name" type="text" class="required">
        <label for="surname">Last name *</label>
        <input id="surname" name="surname" type="text" class="required">
        <p>(*) Mandatory</p>
    </section>
    <h3>Hints</h3>
    <section>
        <ul>
            <li>Foo</li>
            <li>Bar</li>
            <li>Foobar</li>
        </ul>
    </section>
    <h3>Finish</h3>
    <section>
        <input id="acceptTerms" name="acceptTerms" type="checkbox" class="required"> <label for="acceptTerms">I agree with the Terms and Conditions.</label>
    </section>
</div>

var form = $("#contact");
form.validate({
errorPlacement: function errorPlacement(error, element) { element.before(error); },
rules: {
    confirm: {
        equalTo: "#password"
    }
}
});
form.children("div").steps({
headerTag: "h3",
bodyTag: "section",
transitionEffect: "slideLeft",
onStepChanging: function (event, currentIndex, newIndex)
{

    form.validate().settings.ignore = ":disabled,:hidden";
    return form.valid();

},
onFinishing: function (event, currentIndex)
{
    form.validate().settings.ignore = ":disabled";
    return form.valid();
},
onFinished: function (event, currentIndex)
{
    alert("Submitted!");
}
});

$('#specialNumber').on('keyup', function (e) {
    if (!this.value.match(/^(6|8|10|12)$/)) {       
        $(this).addClass('error-color'); // adding error class
    } else {
        $(this).removeClass('error-color'); // remove error class
    }
});

Solution

  • For the moment, the wrong format just take the red color ...

    That's because you're not using the validation plugin for this part of your form evaluation. For some reason you created an event handler to do this totally outside of the validation plugin's parameters.

    Now I want to forbid next step if the input is not on the right format.

    You only have the required rule thanks to class="required" on this field, which is automatically picked up by the validation plugin. So once it's filled out, the validation plugin is satisfied and allows the next step. To validate anything else for this field, you'll need to apply the appropriate rules via methods built into this plugin. You cannot just use a keyup event to color it red and expect the validation plugin to do anything with that.

    Right here is the issue...

    $('#specialNumber').on('keyup', function (e) {
        if (!this.value.match(/^(6|8|10|12)$/)) {       
            $(this).addClass('error-color'); // adding error class
        } else {
            $(this).removeClass('error-color'); // remove error class
        }
    });
    

    With your custom keyup function, you are basically just doing your own validation test and changing the color. ← How do you expect the validation plugin to handle that?

    Remove your keyup function.

    The correct way is to write a custom rule, or use built-in rules, within the validation plugin and then everything will work as expected.

    rules: {
        ... 
        specialNumber: {
            pattern: /^(6|8|10|12)$/  // <- use the pattern rule for regex
        }
        ....
    

    NOTE: to use the pattern, rule, you must include the additional-methods.js file.

    Working DEMO: jsfiddle.net/j8n0o9ty/