41

I'm using forms basic validation to check if email is correct format, then the data is sent by Ajax where it checks if email address is already in use and did the user select country/state or left default values in select boxes.

But for HTML5 form validation to be done submit event is needed, upon clicking submit if it passes that basic form validation Ajax operation is performed, but then when results come in I would like to use the same browser tooltips for interface consistency (and well I like how they look).

So is there a way to make them show up, I was unable to find if there is some special event for them or something like firing submit event but stopping it right away. Right now the field only gets a red edge and error message appears on hovering mouse over it, while the tooltip shows on again clicking submit button.

Also for browsers that don't have native tooltips(in my case Safari) I'm using Webshims Lib and it acts exactly the same as in Chrome and Firefox.

Alexxandar
  • 975
  • 2
  • 11
  • 23

10 Answers10

61

I thought .checkValidity() would do the trick, but it doesn't trigger the UI. (caniuse)

It sounds like .reportValidity() does what you want. (caniuse)

Flimm
  • 136,138
  • 45
  • 251
  • 267
Ben Boyle
  • 1,686
  • 16
  • 13
  • 3
    Chrome and Opera now support `.reportValidity()` https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reportValidity – Keith May 06 '15 at 19:34
  • 2
    if checkValidity is not supported `if(!$('#form')[0].checkValidity()) setTimeout(function () { $('#form button').click();}, 100);` – Simon Jan 08 '18 at 20:06
13

You can find an answer at this link: How to force a html5 form validation without submitting it via jQuery

Basically, you find a submit button and call click on it:

// force form validation
document.getElementById("submitbutton").click()

You can also change validation message after checking if email address is in use or not and then force form validation as above:

document.getElementById("email").setCustomValidity("This email is already registered!");
document.getElementById("submitbutton").click()
Community
  • 1
  • 1
oldbam
  • 2,397
  • 1
  • 16
  • 24
  • 5
    But what if the form is valid? Then it would submit it. :/ Alexxandar just wants to check for validity and display a validity message without submitting. – Glorious Kale Jan 15 '13 at 08:04
  • 4
    by calling setCustomValidity with anything other than an empty string, you are forcing the form to be invalid. As such, it won't submit. – Noishe Jan 02 '14 at 11:10
  • how do you shim it for ie8? – SuperUberDuper Sep 30 '15 at 10:30
  • jQuery is irrelevant here, the same can be accomplished using vanilla JS. – Madbreaks Feb 06 '18 at 19:50
  • 1
    @Madbreaks jQuery is relevant because that's where oldbam found the solution, and it's proper to cite your sources. Nowhere does his answer say it relies on having jQuery. In fact, oldbam's original answer only specified a URL (that happened to have "jquery" in it). The actual title of that page was inserted by a StackOverflow bot! – Auspex Aug 20 '19 at 12:20
5

A polyfill for HTMLFormElement.reportValidity().
Tested with IE11 and Edge. But when running in the StackOverflow sandbox below with IE11, the validation messages are not displayed.

function reportValidityPolyfill() {
  const button = createInvisibleSubmitButton();
  this.appendChild(button);
  this.addEventListener("submit", submitEventHandler);
  var isValid = false;
  button.click();
  this.removeEventListener("submit", submitEventHandler);
  this.removeChild(button);
  return isValid;

  function createInvisibleSubmitButton() {
    const button = document.createElement("button");
    button.type = "submit";
    button.style.display = "none";
    return button;
  }

  function submitEventHandler(event) {
    event.preventDefault();
    isValid = true;
  }
}

if (!HTMLFormElement.prototype.reportValidity) {
  HTMLFormElement.prototype.reportValidity = reportValidityPolyfill;
  console.log("ReportValidity polyfill installed.");
} else {
  console.log("ReportValidity polyfill skipped.");
}
input {
  outline: 1px solid #0f0;
}

input:invalid {
  outline: 1px solid #f00;
}
<form id="form1">
  Enter a number from 1 to 5: <input type="number" min="1" max="5" required>
</form>
<br>
<div onclick="console.log('Validity: ' + document.getElementById('form1').reportValidity())">
  Click here to call reportValidity()
</div>
Christian d'Heureuse
  • 5,090
  • 1
  • 32
  • 28
4

It's actually very simple - add a hidden input element to your form:

<input type="hidden" id="myFormCheck" required="true" value=""/>

Call myInputField.setCustomValidity(message) on the input element you want to create a custom tooltip on then call your form.click();

The form validity process runs and displays the message popup over that element, but the form won't submit because of the hidden element, so you won't need to catch and cancel the submit event.

When you're done and really ready to go, set a value on the hidden element and the form will submit normally.

This way you can use the form tooltip for something like checking for usernames that are available, or matching any value over an HTTP Request etc.

Neil
  • 1,928
  • 19
  • 14
3

As most people say you have to use input.setCustomValidity("message").

The problem here is that you can't check that validation within the submit event, since you need to do an ajax call and then set setCustomValidity asynchronously.

So basically you have to use the change event of the input field and make the ajax call on every change. Or remove the submit button and use the click event of a normal button, check the unique email in the ajax call and then call submit through javascript.

See an example of the last option using jQuery:

<form action="/sign-in" id="form">
    <input type="email" id="email" required/>
    <button id="submit">Submit</button>
</form>
// we capture the click instead the submit
$("#submit").on("click",function(){
    var $elem = $("#email");
    var email = $elem.val();

    //the ajax call returns true if the email exists
    $.get( "ajax/checkUniqueEmail", function(data) {
        if(data === "true"){
            $elem.setCustomValidity("This email already exists.");
        }else{
            $elem.setCustomValidity("")
        }
        //then we submit the form
        $("#form").submit();
    });
});
Ma Jerez
  • 4,887
  • 3
  • 23
  • 21
2

Checkout this link ( Provide custom validation messages using setCustomValidity in HTML 5 pages ).

In the above link, he used "input" type is number and oninput he called the validation function. Let me know is this what you are looking for.

<input type="number" required="true" value="50" min="18" max="60" step="1" oninput="validate(this)">
thomasbabuj
  • 3,779
  • 3
  • 24
  • 22
  • 1
    This is good, but how do you show the browser-looking message div? – Glorious Kale Jan 15 '13 at 08:07
  • `required` is a boolean attribute. You don't need to set it to any value at all, just include the attribute. The mere presence of it is enough for a boolean attribute to work. – Scott Marcus Apr 23 '17 at 18:54
1

Here's a nice live example that custom validates/gives feedback on a form input.

The basic javascript looks like:

function checkPasscode() {
    var passcode_input = document.querySelector("#passcode");

    if (passcode_input.value != "Ivy") {
        passcode_input.setCustomValidity("Wrong. It's 'Ivy'.");
    } else {
        passcode_input.setCustomValidity(""); // be sure to leave this empty!
        alert("Correct!");
    }
}

HTML:

<form>
    <label for="passcode">Enter Passcode:</label>
    <input id="passcode" 
           type="password" 
           placeholder="Your passcode" 
           oninput="checkPasscode();"
           required/>
    <button type="submit">Submit</button>
</form>
zelusp
  • 3,500
  • 3
  • 31
  • 65
0

You can use setCustomValidity with for the element if the condition is false ( you can do it inside any event handler such as keypress or click ). If the input is NOT valid, SUBMIT. This will trigger the browser's message tooltip.

Glorious Kale
  • 1,273
  • 15
  • 25
0

setCustomValidity() does the trick on my change password from, confirm password input.

But the problem is when we set setCustomValidity('Passwords do not match) it doesn't clear as attached to the form submit event.

I just added setCustomValidity('') to blank in password confirmation input key up event.

It works for me.

 $(document).ready(function() {
            const confirm = document.querySelector('input[name=password2]');
            $('#pass2').on('keyup', function(){
                confirm.setCustomValidity('');
            })
            $("#reset-pw-form").on('submit', function(e) {
                e.preventDefault();
                if($('#pass1').val() != $('#pass2').val())  {
                    confirm.setCustomValidity('Passwords do not match');
                    confirm.reportValidity();
                    return false;
                }

}

Dumindu Perera
  • 1,571
  • 15
  • 13
0

As you already have divs to display feedback, you can manually manipulate these.

$('#cc').on('input', function () {
  var input = document.getElementById("cc");
  var validity = document.getElementById("validity");
  validity.style.display = "block";
  if (checkLuhn(input.value)) {
    validity.innerHTML = "Valid Credit Card Number";
  } else {
    validity.innerHTML = "Invalid Credit Card Number";
  }
});

You should also check the length of the credit card number is either 13 or 16 all numeric digits.

Andy Gee
  • 3,149
  • 2
  • 29
  • 44