Skip to content
Advertisement

Custom HTML5 form validation not showing custom error initially

Basic HTML5 form with custom validation. If the submitted value is not a number, the browser should display the error message “Field must be an number.” If you enter “abc” and press submit (or hit enter) the field is marked as invalid, but the error message does not appear. Press submit again (or hit enter) and it will show the message. This double-submit behavior appears on latest versions of Firefox, Chrome, Safari, and IE on Windows and OS X. You will notice that the default “this field is required…” message appears upon the first submission and does not exhibit the odd behavior.

http://jsfiddle.net/6gsr3r4b/

As an aside, I am well aware that this validation will not work in older versions of IE and that the input field could have a type of number that would automatically complete this validation; this is simplified example of my problem for demonstration purposes only.

Javscript

var form = document.getElementById("form");
var field = document.getElementById("field");

form.onsubmit = validateForm;

function validateForm() {

    if(isNaN(field.value)) {
        field.setCustomValidity("Field must be a number.");
    } else {
        return true;
    }

    return false;
}

HTML

<form id="form">
    <label for="field">Favorite number</label>
    <input type="text" id="field" required>
    <input type="submit">
</form>

Advertisement

Answer

After setting the validity message, you need to call element.reportValidity() to make it show up.

setCustomValidity(message)

Sets a custom error message string to be shown to the user upon submitting the form, explaining why the value is not valid — when a message is set, the validity state is set to invalid. To clear this state, invoke the function with an empty string passed as its argument. In this case the custom error message is cleared, the element is considered valid, and no message is shown.

reportValidity()

Checks the element’s value against its constraints and also reports the validity status; if the value is invalid, it fires an invalid event at the element, returns false, and then reports the validity status to the user in whatever way the user agent has available. Otherwise, it returns true.

You also need to use event.preventDefault() on the form submission event whenever the input is invalid, so that the form submission doesn’t go through.

Here is an example:

var form = document.getElementById('form');
var field = document.getElementById('field');

form.onsubmit = validateForm;

/* this is the function that actually marks the field as valid or invalid */
function validateForm(event) {
    if (isNaN(field.value)) {
        field.setCustomValidity('Field must be a number.');
        field.reportValidity();
        event.preventDefault();
    }
    
    field.setCustomValidity('');
}
<form id="form">
    <label for="field">Favorite number</label>
    <input type="text" id="field" required />
    <input type="submit" />
</form>

You can also use the HTML5 pattern attribute to do most form validation without JavaScript, or augmented with JavaScript to set custom error messages.

Pattern: A regular expression that the control’s value is checked against. The pattern must match the entire value, not just some subset. Use the title attribute to describe the pattern to help the user. This attribute applies when the value of the type attribute is text, search, tel, url or email; otherwise it is ignored. The regular expression language is the same as JavaScript’s. The pattern is not surrounded by forward slashes.

<form id="form">
  <label for="field">Favorite number</label>
  <input type="text" id="field" pattern="d*" title="Field must be a number." required />
  <input type="submit" />
</form>
Advertisement