API de validation des contraintes JavaScript
Apprenez l'API Constraint Validation HTML5 en JavaScript : checkValidity, reportValidity, setCustomValidity, l'objet ValidityState, messages d'erreur personnalisés, correspondance de motifs et validation de formulaire en temps réel.
JavaScript est un langage essentiel au développement web, permettant du contenu dynamique et une interaction utilisateur enrichie. Un aspect critique de JavaScript dans les formulaires web est l'API Constraint Validation HTML5. Ce guide explore l'API en profondeur — ses méthodes, l'object ValidityState, et comment construire des messages personnalisés et des retours en temps réel — avec des exemples pratiques pour les développeurs débutants comme expérimentés.
Cette page s'appuie sur l'utilisation des formulaires dans le DOM et l'événement et la méthode submit. Si vous devez lire ou envoyer les données du formulaire après validation, consultez les propriétés et méthodes de formulaire et FormData.
Introduction à l'API Constraint Validation HTML5
L'API Constraint Validation HTML5 fournit une validation native côté client des éléments de formulaire, interceptant les erreurs avant la soumission du formulaire. Les contraintes sont déclarées directement dans le HTML via des attributs tels que required, type="email", min, max, minlength, maxlength, step et pattern. Le navigateur les applique automatiquement et les expose à JavaScript pour que vous puissiez personnaliser l'expérience.
La validation côté client rend les formulaires plus réactifs et réduit les allers-retours inutiles vers le serveur. Ce n'est cependant pas une limite de sécurité — un utilisateur peut la contourner entièrement en désactivant JavaScript ou en forgeant sa propre requête. Validez toujours de nouveau côté serveur.
La surface de l'API Constraint Validation
Chaque élément associé à un formulaire (<input>, <textarea>, <select>, <button>, <fieldset>, et le <form> lui-même) expose le même petit ensemble de membres.
Méthodes
element.checkValidity()— retournetruesi l'élément satisfait toutes ses contraintes, sinonfalse. En cas d'échec, il déclenche également un événementinvalidsur l'élément.element.reportValidity()— commecheckValidity(), mais affiche en plus la bulle d'erreur native du navigateur pour le premier champ invalide. Utile lorsque vous voulez l'interface native sans message personnalisé.element.setCustomValidity(message)— définit une chaîne d'erreur personnalisée. Une string non vide marque l'élément comme invalide ; une string vide ('') efface l'erreur personnalisée et permet à l'élément d'être à nouveau valide.form.checkValidity()/form.reportValidity()— valident tous les contrôles du formulaire en une seule fois.
Propriétés
element.validity— un objectValidityStateen lecture seule décrivant pourquoi le champ est invalide.element.validationMessage— le message localisé que le navigateur afficherait pour l'état invalide actuel (vide lorsque valide).element.willValidate—truesi l'élément sera vérifié lors de la validation (les champs désactivés etreadonlysont ignorés).
L'object ValidityState
element.validity expose un boolean pour chaque type d'échec, plus valid :
| Propriété | true quand… |
|---|---|
valueMissing | un champ required est vide |
typeMismatch | la valeur est du mauvais type (ex. un type="email" mal formé) |
patternMismatch | la valeur ne correspond pas à l'attribut pattern |
tooShort / tooLong | la valeur est plus courte/longue que minlength/maxlength |
rangeUnderflow / rangeOverflow | un nombre/date est inférieur à min ou supérieur à max |
stepMismatch | la valeur ne correspond pas à l'incrément step |
customError | setCustomValidity() a reçu un message non vide |
valid | le champ passe toutes les contraintes |
Inspecter ces indicateurs vous permet d'adapter le message au problème exact :
const input = document.querySelector('#age');
const v = input.validity;
if (v.valueMissing) {
input.setCustomValidity('Age is required.');
} else if (v.rangeUnderflow) {
input.setCustomValidity('You must be at least 18.');
} else {
input.setCustomValidity(''); // clears the custom error
}Mise en place de votre première validation
Avant de plonger dans des règles complexes, commencez par les bases : vérifier qu'un champ required n'est pas vide.
Ajouter l'attribut novalidate à un formulaire désactive l'interface de validation par défaut du navigateur. L'API Constraint Validation fonctionne toujours en JavaScript — checkValidity() et validity restent précis — vous pouvez donc construire votre propre retour tout en supprimant les bulles natives.
<form id="registrationForm" novalidate>
<label for="username">Username:</label>
<input type="text" id="username" required />
<button type="submit">Register</button>
<span id="usernameError" style="color: red;"></span>
<span id="registerSuccess" style="color: green; display: none;">Registration successful!</span>
</form>
<script>
document.getElementById('registrationForm').addEventListener('submit', function(event) {
event.preventDefault();
const input = document.getElementById('username');
const usernameError = document.getElementById('usernameError');
const registerSuccess = document.getElementById('registerSuccess');
if (!input.checkValidity()) {
usernameError.textContent = 'Username is required.';
registerSuccess.style.display = 'none'; // Hide success message if visible
} else {
usernameError.textContent = ''; // Clear error message
registerSuccess.textContent = 'Registration successful!';
registerSuccess.style.display = 'block'; // Show success message
input.value = ''; // Reset the username input
}
});
</script>Cet extrait de code illustre la configuration de base où la vérification input.checkValidity() est utilisée pour rendre un champ obligatoire. Le formulaire déclenchera un message d'erreur si le champ nom d'utilisateur est laissé vide.
Implémentation de messages de validation personnalisés
En allant au-delà des messages d'alerte par défaut du navigateur, vous pouvez créer une expérience utilisateur plus intégrée en affichant des messages d'erreur personnalisés dans la mise en page HTML. Voici comment procéder :
Notez que la validation d'e-mail HTML5 par défaut n'exige pas forcément un domaine de premier niveau, permettant à des saisies comme w3docs@aol de passer comme valides. Pour s'assurer que les adresses e-mail incluent un domaine, nous avons ajouté un motif plus strict .+@.+\..+ au champ de saisie d'e-mail. Cette expression régulière exige au moins un point après le symbole @, correspondant plus fidèlement aux formats d'e-mail réels. (Pour apprendre la syntaxe regex derrière les motifs, voir les ancres pour le début et la fin de chaîne.)
<form id="contactForm" novalidate>
<label for="email">Email:</label>
<input type="email" id="email" pattern=".+@.+\..+" required />
<button type="submit">Submit</button>
<span id="emailError" style="color: red"></span>
<span id="successMessage" style="color: green; display: none;">Submission successful!</span>
</form>
<script>
document.getElementById("contactForm").addEventListener("submit", function (event) {
event.preventDefault(); // Prevent default form submission
const email = document.getElementById("email");
const errorMessage = document.getElementById("emailError");
const successMessage = document.getElementById("successMessage");
if (!email.checkValidity()) {
errorMessage.textContent = "Please enter a valid email address, including a domain."; // Display custom error message
successMessage.style.display = "none"; // Hide success message if visible
} else {
errorMessage.textContent = ""; // Clear the error message
successMessage.textContent = "Submission successful!";
successMessage.style.display = "block"; // Show success message
email.value = ""; // Reset the email input
}
});
</script>Ce code améliore l'expérience utilisateur en fournissant un retour immédiat et en ligne sur la validité de la saisie d'e-mail.
Amélioration des validations de formulaire avec des motifs
Parfois, des validations plus spécifiques sont nécessaires, comme vérifier que la saisie correspond à un certain motif. Cela est couramment utilisé pour les numéros de téléphone, les codes postaux et les champs similaires. L'attribut pattern est ancré implicitement — la valeur entière doit correspondre — ainsi [0-9]{3}-[0-9]{3}-[0-9]{4} accepte 123-456-7890 mais rejette 1234567890.
<form id="signupForm" novalidate>
<label for="phone">Phone (XXX-XXX-XXXX):</label>
<input type="tel" id="phone" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}" required />
<button type="submit">Sign Up</button>
<span id="phoneError" style="color:red;"></span>
<span id="successMessage" style="color:green; display:none;">Submission successful!</span>
</form>
<script>
document.getElementById('signupForm').addEventListener('submit', function(event) {
const phone = document.getElementById('phone');
const phoneError = document.getElementById('phoneError');
const successMessage = document.getElementById('successMessage');
if (!phone.checkValidity()) {
phoneError.textContent = 'Please enter a phone number in the format XXX-XXX-XXXX.';
successMessage.style.display = 'none'; // Hide success message if present
} else {
phoneError.textContent = '';
phone.value = ''; // Reset the input field
successMessage.textContent = 'Submission successful!';
successMessage.style.display = 'block'; // Show success message
}
});
</script>Cet exemple utilise l'attribut pattern pour spécifier que le numéro de téléphone doit correspondre à un format précis, améliorant ainsi la qualité des données collectées via le formulaire.
Validation en temps réel avec l'object ValidityState
Attendre jusqu'à la soumission peut sembler lent. En écoutant l'événement input et en lisant les indicateurs de validity, vous pouvez donner un retour au fur et à mesure que l'utilisateur tape et formuler un message pour l'échec exact :
<form id="profileForm" novalidate>
<label for="user">Username (3-12 letters/digits):</label>
<input type="text" id="user" pattern="[A-Za-z0-9]{3,12}" required />
<span id="userMsg" style="color:red;"></span>
</form>
<script>
const user = document.getElementById('user');
const msg = document.getElementById('userMsg');
user.addEventListener('input', function () {
const v = user.validity;
if (v.valueMissing) {
msg.textContent = 'Username is required.';
} else if (v.patternMismatch) {
msg.textContent = 'Use 3-12 letters or digits only.';
} else {
msg.textContent = ''; // valid
}
});
</script>Ici valueMissing et patternMismatch proviennent directement de l'object ValidityState, donc un seul gestionnaire signale la raison précise sans réimplémenter manuellement les règles.
Combiner règles déclaratives et personnalisées
Certaines vérifications — comme « les mots de passe doivent correspondre » — ne peuvent pas être exprimées avec des attributs HTML. Utilisez setCustomValidity() pour les intégrer dans le même pipeline de validation :
const password = document.getElementById('password');
const confirm = document.getElementById('confirm');
confirm.addEventListener('input', function () {
if (confirm.value !== password.value) {
confirm.setCustomValidity('Passwords do not match.');
} else {
confirm.setCustomValidity(''); // clear so the field becomes valid
}
});Parce que l'erreur personnalisée participe à checkValidity(), le gestionnaire de soumission du formulaire n'a pas besoin de cas particulier — le champ non concordant est simplement signalé comme invalide comme n'importe quel autre.
Conclusion
L'API Constraint Validation HTML5 est un outil puissant pour les développeurs web souhaitant implémenter une validation de formulaire côté client. Elle améliore non seulement l'expérience utilisateur en fournissant un retour immédiat, mais réduit également la charge sur le serveur. En suivant les exemples fournis dans ce guide, vous pouvez créer des formulaires web plus robustes, efficaces et conviviaux. Pour un retour en temps réel, pensez également à écouter les événements input ou change en parallèle du gestionnaire de soumission.