The Constraint Validation API
The Constraint Validation API consists of a set of methods and properties available on the following form element DOM interfaces:
HTMLButtonElement(represents a<button>element)HTMLFieldSetElement(represents a<fieldset>element)HTMLInputElement(represents an<input>element)HTMLOutputElement(represents an<output>element)HTMLSelectElement(represents a<select>element)HTMLTextAreaElement(represents a<textarea>element)
The Constraint Validation API makes the following properties available on the above elements.
validationMessage: Returns a localized message describing the validation constraints that the control doesn’t satisfy (if any). If the control is not a candidate for constraint validation (willValidateisfalse) or the element’s value satisfies its constraints (is valid), this will return an empty string.validity: Returns aValidityStateobject that contains several properties describing the validity state of the element. You can find full details of all the available properties in theValidityStatereference page; below is listed a few of the more common ones:patternMismatch: Returnstrueif the value does not match the specifiedpattern, andfalseif it does match. If true, the element matches the:invalidCSS pseudo-class.tooLong: Returnstrueif the value is longer than the maximum length specified by themaxlengthattribute, orfalseif it is shorter than or equal to the maximum. If true, the element matches the:invalidCSS pseudo-class.tooShort: Returnstrueif the value is shorter than the minimum length specified by theminlengthattribute, orfalseif it is greater than or equal to the minimum. If true, the element matches the:invalidCSS pseudo-class.rangeOverflow: Returnstrueif the value is greater than the maximum specified by themaxattribute, orfalseif it is less than or equal to the maximum. If true, the element matches the:invalidand:out-of-rangeCSS pseudo-classes.rangeUnderflow: Returnstrueif the value is less than the minimum specified by theminattribute, orfalseif it is greater than or equal to the minimum. If true, the element matches the:invalidand:out-of-rangeCSS pseudo-classes.typeMismatch: Returnstrueif the value is not in the required syntax (whentypeisemailorurl), orfalseif the syntax is correct. Iftrue, the element matches the:invalidCSS pseudo-class.valid: Returnstrueif the element meets all its validation constraints, and is therefore considered to be valid, orfalseif it fails any constraint. If true, the element matches the:validCSS pseudo-class; the:invalidCSS pseudo-class otherwise.valueMissing: Returnstrueif the element has arequiredattribute, but no value, orfalseotherwise. If true, the element matches the:invalidCSS pseudo-class.
willValidate: Returnstrueif the element will be validated when the form is submitted;falseotherwise.
// There are many ways to pick a DOM node; here we get the form itself and the email
// input box, as well as the span element into which we will place the error message.
const form = document.querySelector("form");
const email = document.getElementById("mail");
const emailError = document.querySelector("#mail + span.error");
email.addEventListener("input", (event) => {
// Each time the user types something, we check if the
// form fields are valid.
if (email.validity.valid) {
// In case there is an error message visible, if the field
// is valid, we remove the error message.
emailError.textContent = ""; // Reset the content of the message
emailError.className = "error"; // Reset the visual state of the message
} else {
// If there is still an error, show the correct error
showError();
}
});
form.addEventListener("submit", (event) => {
// if the email field is valid, we let the form submit
if (!email.validity.valid) {
// If it isn't, we display an appropriate error message
showError();
// Then we prevent the form from being sent by canceling the event
event.preventDefault();
}
});
function showError() {
if (email.validity.valueMissing) {
// If the field is empty,
// display the following error message.
emailError.textContent = "You need to enter an email address.";
} else if (email.validity.typeMismatch) {
// If the field doesn't contain an email address,
// display the following error message.
emailError.textContent = "Entered value needs to be an email address.";
} else if (email.validity.tooShort) {
// If the data is too short,
// display the following error message.
emailError.textContent = `Email should be at least ${email.minLength} characters; you entered ${email.value.length}.`;
}
// Set the styling appropriately
emailError.className = "error active";
}
function checkZIP() {
// For each country, defines the pattern that the ZIP has to follow
const constraints = {
ch: [
"^(CH-)?\\d{4}$",
"Switzerland ZIPs must have exactly 4 digits: e.g. CH-1950 or 1950",
],
fr: [
"^(F-)?\\d{5}$",
"France ZIPs must have exactly 5 digits: e.g. F-75012 or 75012",
],
de: [
"^(D-)?\\d{5}$",
"Germany ZIPs must have exactly 5 digits: e.g. D-12345 or 12345",
],
nl: [
"^(NL-)?\\d{4}\\s*([A-RT-Z][A-Z]|S[BCE-RT-Z])$",
"Netherland ZIPs must have exactly 4 digits, followed by 2 letters except SA, SD and SS",
],
};
// Read the country id
const country = document.getElementById("Country").value;
// Get the NPA field
const ZIPField = document.getElementById("ZIP");
// Build the constraint checker
const constraint = new RegExp(constraints[country][0], "");
console.log(constraint);
// Check it!
if (constraint.test(ZIPField.value)) {
// The ZIP follows the constraint, we use the ConstraintAPI to tell it
ZIPField.setCustomValidity("");
} else {
// The ZIP doesn't follow the constraint, we use the ConstraintAPI to
// give a message about the format required for this country
ZIPField.setCustomValidity(constraints[country][1]);
}
}