Manually Triggering Form Validation using jQuery
Asked Answered
J

12

134

I have a form with several different fieldsets. I have some jQuery that displays the field sets to the users one at a time. For browsers that support HTML5 validation, I'd love to make use of it. However, I need to do it on my terms. I'm using JQuery.

When a user clicks a JS Link to move to the next fieldset, I need the validation to happen on the current fieldset and block the user from moving forward if there is issues.

Ideally, as the user loses focus on an element, validation will occur.

Currently have novalidate going and using jQuery. Would prefer to use the native method. :)

Joella answered 25/9, 2011 at 21:6 Comment(0)
R
79

You can't trigger the native validation UI (see edit below), but you can easily take advantage of the validation API on arbitrary input elements:

$('input').blur(function(event) {
    event.target.checkValidity();
}).bind('invalid', function(event) {
    setTimeout(function() { $(event.target).focus();}, 50);
});

The first event fires checkValidity on every input element as soon as it loses focus, if the element is invalid then the corresponding event will be fired and trapped by the second event handler. This one sets the focus back to the element, but that could be quite annoying, I assume you have a better solution for notifying about the errors. Here's a working example of my code above.

EDIT: All modern browsers support the reportValidity() method for native HTML5 validation, per this answer.

Rembert answered 26/9, 2011 at 23:16 Comment(8)
Golden sentence "You can't trigger the native validation UI". In my case (custom JS tricks + Browser html5 validation + UI tooltips) I had no choice than go for hidden submit button at the end to get bothPhotosphere
If your form doesn't have a submit button, you can fake one: $('<input type="submit">').hide().appendTo($myForm).click().remove();Multiped
@Multiped Wouldn't a form.submit() work just fine? Or does HTML5 require a submit button for the validation now?Clamorous
@Clamorous Calling .submit() does not work for me. @philfreo's solution works. Hmm.Clematis
Just a reminder that checkValidity only checks it, but does not popup the browser's standard hint. If you want the popup too - use element.reportValidity()Attic
is there still no way to trigger native validation UI (i.e. causing one the inputs to be viewed as "invalid" by the browser)?Byer
@Alex i thought this would be what i was looking for. what i am doing is validating the user input against a massive array of values in JS; if the array does not contain the value, then id like to trigger the invalid event for that input element, in turn triggering the native invalid UI. is this somehow possible to do using reportValidity()?Byer
The only issue of this solution is if we have more than one required field of this form then the autofocus will have an infinite loop since validation triggers when focus leaves from an inputJeggar
D
230

TL;DR: Not caring about old browsers? Use form.reportValidity().

Need legacy browser support? Read on.


It actually is possible to trigger validation manually.

I'll use plain JavaScript in my answer to improve reusability, no jQuery is needed.


Assume the following HTML form:

<form>
  <input required>
  <button type="button">Trigger validation</button>
</form>

And let's grab our UI elements in JavaScript:

var form = document.querySelector('form')
var triggerButton = document.querySelector('button')

Don't need support for legacy browsers like Internet Explorer? This is for you.

All modern browsers support the reportValidity() method on form elements.

triggerButton.onclick = function () {
    form.reportValidity()
}

That's it, we're done. Also, here's a simple CodePen using this approach.


Approach for older browsers

Below is a detailed explanation how reportValidity() can be emulated in older browsers.

However, you don't need to copy&paste those code blocks into your project yourself — there is a ponyfill/polyfill readily available for you.

Where reportValidity() is not supported, we need to trick the browser a little bit. So, what will we do?

  1. Check validity of the form by calling form.checkValidity(). This will tell us if the form is valid, but not show the validation UI.
  2. If the form is invalid, we create a temporary submit button and trigger a click on it. Since the form is not valid, we know it won't actually submit, however, it will show validation hints to the user. We'll remove the temporary submit button immedtiately, so it will never be visible to the user.
  3. If the form is valid, we don't need to interfere at all and let the user proceed.

In code:

triggerButton.onclick = function () {
  // Form is invalid!
  if (!form.checkValidity()) {
    // Create the temporary button, click and remove it
    var tmpSubmit = document.createElement('button')
    form.appendChild(tmpSubmit)
    tmpSubmit.click()
    form.removeChild(tmpSubmit)

  } else {
    // Form is valid, let the user proceed or do whatever we need to
  }
}

This code will work in pretty much any common browser (I've tested it successfully down to IE11).

Here's a working CodePen example.

Dimond answered 15/1, 2018 at 16:29 Comment(4)
This should be the accepted answer in 2021.Dogy
That answer is obviously perfect :)Lafountain
Not sure how old would be "old browsers". caniuse.com/constraint-validation. I guess you could call them legacy browsers now :PEncode
jQuery Example: $('#myFormId')..get(0).reportValidity();Randirandie
R
79

You can't trigger the native validation UI (see edit below), but you can easily take advantage of the validation API on arbitrary input elements:

$('input').blur(function(event) {
    event.target.checkValidity();
}).bind('invalid', function(event) {
    setTimeout(function() { $(event.target).focus();}, 50);
});

The first event fires checkValidity on every input element as soon as it loses focus, if the element is invalid then the corresponding event will be fired and trapped by the second event handler. This one sets the focus back to the element, but that could be quite annoying, I assume you have a better solution for notifying about the errors. Here's a working example of my code above.

EDIT: All modern browsers support the reportValidity() method for native HTML5 validation, per this answer.

Rembert answered 26/9, 2011 at 23:16 Comment(8)
Golden sentence "You can't trigger the native validation UI". In my case (custom JS tricks + Browser html5 validation + UI tooltips) I had no choice than go for hidden submit button at the end to get bothPhotosphere
If your form doesn't have a submit button, you can fake one: $('<input type="submit">').hide().appendTo($myForm).click().remove();Multiped
@Multiped Wouldn't a form.submit() work just fine? Or does HTML5 require a submit button for the validation now?Clamorous
@Clamorous Calling .submit() does not work for me. @philfreo's solution works. Hmm.Clematis
Just a reminder that checkValidity only checks it, but does not popup the browser's standard hint. If you want the popup too - use element.reportValidity()Attic
is there still no way to trigger native validation UI (i.e. causing one the inputs to be viewed as "invalid" by the browser)?Byer
@Alex i thought this would be what i was looking for. what i am doing is validating the user input against a massive array of values in JS; if the array does not contain the value, then id like to trigger the invalid event for that input element, in turn triggering the native invalid UI. is this somehow possible to do using reportValidity()?Byer
The only issue of this solution is if we have more than one required field of this form then the autofocus will have an infinite loop since validation triggers when focus leaves from an inputJeggar
B
23

In some extent, You CAN trigger HTML5 form validation and show hints to user without submitting the form!

Two button, one for validate, one for submit

Set a onclick listener on the validate button to set a global flag(say justValidate) to indicate this click is intended to check the validation of the form.

And set a onclick listener on the submit button to set the justValidate flag to false.

Then in the onsubmit handler of the form, you check the flag justValidate to decide the returning value and invoke the preventDefault() to stop the form to submit. As you know, the HTML5 form validation(and the GUI hint to user) is preformed before the onsubmit event, and even if the form is VALID you can stop the form submit by returning false or invoke preventDefault().

And, in HTML5 you have a method to check the form's validation: the form.checkValidity(), then in you can know if the form is validate or not in your code.

OK, here is the demo: http://jsbin.com/buvuku/2/edit

Bremerhaven answered 26/12, 2014 at 3:45 Comment(0)
B
3

var field = $("#field")
field.keyup(function(ev){
    if(field[0].value.length < 10) {
        field[0].setCustomValidity("characters less than 10")
        
    }else if (field[0].value.length === 10) {
        field[0].setCustomValidity("characters equal to 10")
        
    }else if (field[0].value.length > 10 && field[0].value.length < 20) {
        field[0].setCustomValidity("characters greater than 10 and less than 20")
        
    }else if(field[0].validity.typeMismatch) {
    	field[0].setCustomValidity("wrong email message")
        
    }else {
    	field[0].setCustomValidity("") // no more errors
        
    }
    field[0].reportValidity()
    
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="email" id="field">
Baguette answered 1/3, 2019 at 11:53 Comment(1)
Would you add more explanation?Quiescent
S
2

Somewhat easy to make add or remove HTML5 validation to fieldsets.

 $('form').each(function(){

    // CLEAR OUT ALL THE HTML5 REQUIRED ATTRS
    $(this).find('.required').attr('required', false);

    // ADD THEM BACK TO THE CURRENT FIELDSET
    // I'M JUST USING A CLASS TO IDENTIFY REQUIRED FIELDS
    $(this).find('fieldset.current .required').attr('required', true);

    $(this).submit(function(){

        var current     = $(this).find('fieldset.current')
        var next        = $(current).next()

        // MOVE THE CURRENT MARKER
        $(current).removeClass('current');
        $(next).addClass('current');

        // ADD THE REQUIRED TAGS TO THE NEXT PART
        // NO NEED TO REMOVE THE OLD ONES
        // SINCE THEY SHOULD BE FILLED OUT CORRECTLY
        $(next).find('.required').attr('required', true);

    });

});
Silicle answered 17/4, 2013 at 22:23 Comment(0)
T
2

I seem to find the trick: Just remove the form target attribute, then use a submit button to validate the form and show hints, check if form valid via JavaScript, and then post whatever. The following code works for me:

<form>
  <input name="foo" required>
  <button id="submit">Submit</button>
</form>

<script>
$('#submit').click( function(e){
  var isValid = true;
  $('form input').map(function() {
    isValid &= this.validity['valid'] ;
  }) ;
  if (isValid) {
    console.log('valid!');
    // post something..
  } else
    console.log('not valid!');
});
</script>
Tekla answered 25/9, 2016 at 16:22 Comment(1)
Thanks! It's the real solution for jQuery.Sop
D
1

Html Code:

<form class="validateDontSubmit">
....
<button style="dislay:none">submit</button>
</form>
<button class="outside"></button>

javascript( using Jquery):

<script type="text/javascript">

$(document).on('submit','.validateDontSubmit',function (e) {
    //prevent the form from doing a submit
    e.preventDefault();
    return false;
})

$(document).ready(function(){
// using button outside trigger click
    $('.outside').click(function() {
        $('.validateDontSubmit button').trigger('click');
    });
});
</script>

Hope this will help you

Dottiedottle answered 20/12, 2018 at 9:13 Comment(2)
Why is it answering the question ?Athiste
it using HTML5 validate without submit. and use Form data for your purpose: form_data = $('.validateDontSubmit').serializeArray();Googolplex
E
1

For input field

<input id="PrimaryPhNumber" type="text" name="mobile"  required
                                       pattern="^[789]\d{9}$" minlenght="10" maxLength="10" placeholder="Eg: 9444400000"
                                       class="inputBoxCss"/>
$('#PrimaryPhNumber').keyup(function (e) {
        console.log(e)
        let field=$(this)
        if(Number(field.val()).toString()=="NaN"){
            field.val('');
            field.focus();
            field[0].setCustomValidity('Please enter a valid phone number');
            field[0].reportValidity()
            $(":focus").css("border", "2px solid red");
        }
    })
Escheat answered 2/9, 2020 at 16:55 Comment(0)
G
1
$('#id').get(0).reportValidity();

This will trigger the input with ID specified. Use ".classname" for classes.

Gelasias answered 3/2, 2023 at 4:31 Comment(0)
I
1

you might want to know that this function reportValidity() always returns a boolean value. You should also know that it's a native JS function so you shouldn't call using jQuery.

So we can do something like this example bellow:

<script>
if (document.getElementById('frmUser').reportValidity()) { 
    $('#frmUser').submit();
}
</script>
Intercostal answered 26/7, 2023 at 14:38 Comment(0)
C
-1

When there is a very complex (especially asynchronous) validation process, there is a simple workaround:

<form id="form1">
<input type="button" onclick="javascript:submitIfVeryComplexValidationIsOk()" />
<input type="submit" id="form1_submit_hidden" style="display:none" />
</form>
...
<script>
function submitIfVeryComplexValidationIsOk() {
    var form1 = document.forms['form1']
    if (!form1.checkValidity()) {
        $("#form1_submit_hidden").click()
        return
    }

    if (checkForVeryComplexValidation() === 'Ok') {
         form1.submit()
    } else {
         alert('form is invalid')
    }
}
</script>
Contain answered 10/1, 2017 at 22:53 Comment(0)
P
-2

Another way to resolve this problem:

$('input').oninvalid(function (event, errorMessage) {
    event.target.focus();
});
Proliferate answered 9/12, 2015 at 16:20 Comment(2)
Doesn't work for me, I get: Uncaught TypeError: $(...).oninvalid is not a function and I do not see it in the jQuery docs.Zinfandel
I think it should be saying "invalid" and not "oninvalid" as you are using jQuery here.Millepore

© 2022 - 2024 — McMap. All rights reserved.