La création de formulaires web a toujours été une tâche complexe. Bien que le balisage du formulaire en lui-même soit plutôt simple, c'est la vérification de la validité et de la cohérence des valeurs de chaque champ qui s'avère difficile. Informer l'utilisatrice ou l'utilisateur à propos de la validité (ou de l'invalidité) des champs est parfois un casse-tête. HTML5 introduit de nouveaux mécanismes pour les formulaires : de nouveaux types sémantiques pour <input>
et la validation des contraintes pour simplifier la vérification du contenu d'un formulaire côté client. Les contraintes de base usuelles peuvent être vérifiées sans recourir à JavaScript à l'aide de nouveaux attributs. Des contraintes plus complexes peuvent être testées à l'aide de l'API Constraint Validation.
Pour une introduction à ces concepts avec des exemples, voir le tutoriel sur la validation des formulaires.
Note : La validation des contraintes HTML ne signifie pas qu'il n'est plus nécessaire de vérifier côté serveur. Même si cela réduit les risques d'envoi de formulaires invalides, des acteurs malveillants pourraient passer outre ces vérifications côté client. Aussi, assurez-vous de toujours valider les contraintes de saisie côté serveur, en étant cohérent avec ce qui est fait côté client.
Contraintes intrinsèques et contraintes de baseEn HTML, les contraintes de base peuvent être déclarées de deux façons :
type
de l'élément <input>
. Ainsi, choisir le type email
créera automatiquement une contrainte vérifiant que la valeur est une adresse électronique valide.Les contraintes intrinsèques portées par l'attribut type
sont :
Pour ces deux types de champ, si l'attribut multiple
est utilisé, plusieurs valeurs peuvent être passées dans le champ sous la forme d'une liste séparée par des virgules. Si au moins une des valeurs ne respecte pas les conditions décrites ici, la violation de contrainte TypeMismatch
est déclenchée.
On notera que la plupart des types de champ n'ont pas de contraintes intrinsèques : soit il n'y a pas de contrainte particulière, soit le navigateur applique un algorithme de transformation pour que les valeurs incorrectes utilisent une valeur par défaut correcte.
Attributs relatifs à la validationEn complément de l'attribut type
mentionné ci-avant, les attributs suivants permettent de décrire des contraintes basiques :
pattern
text
, search
, url
, tel
, email
, password
Une expression rationnelle JavaScript (compilée avec les marqueurs global
, ignoreCase
, et multiline
désactivés). La valeur doit correspondre au motif décrit par l'expression. patternMismatch
min
range
, number
Un nombre valide La valeur du champ doit être supérieure ou égale à la valeur de l'attribut. rangeUnderflow
date
, month
, week
Une date valide datetime-local
, time
Un horodatage valide max
range
, number
Un nombre valide La valeur du champ doit être inférieure ou égale à la valeur de l'attribut. rangeOverflow
date
, month
, week
Une date valide datetime-local
, time
Un horodatage valide required
text
, search
, url
, tel
, email
, password
, date
, datetime-local
, month
, week
, time
, number
, checkbox
, radio
, file
. Ãgalement utilisable sur les éléments <select>
et <textarea>
. Aucune valeur, il s'agit d'un attribut booléen : sa présence indique que la valeur est requise et son absence indique que la valeur est facultative. Si l'attribut est présent, il doit y avoir une valeur. valueMissing
step
date
Un nombre entier (qui exprime des jours) Ã moins que l'attribut vaille any
, la valeur devra être min + un multiple entier de l'incrément. stepMismatch
month
Un nombre entier de mois week
Un nombre entier de semaines datetime-local
, time
Un nombre entier de secondes range
, number
Un entier minlength
text
, search
, url
, tel
, email
, password
. Ãgalement disponible sur l'élément <textarea>
. Une longueur entière Le nombre de caractères, exprimé en points de code, ne doit pas être inférieur à la valeur de l'attribut si ce dernier n'est pas vide. Pour l'élément <textarea>
, les passages à la ligne sont normalisés en un seul caractère (contrairement aux paires CRLF). tooShort
maxlength
text
, search
, url
, tel
, email
, password
. Ãgalement disponible sur l'élément <textarea>
. Une longueur entière Le nombre de caractères, exprimé en points de code, ne doit pas dépasser la valeur de l'attribut. tooLong
Processus de validation des contraintes
En complément de la validation native effectuée par le navigateur, on peut manipuler la validation des contraintes en JavaScript à l'aide de l'API Constraint Validation, sur un élément du formulaire ou sur le formulaire (<form>
). La validation des contraintes a lieu quand :
checkValidity()
ou reportValidity()
depuis une instance d'une interface du DOM correspondant à un élément de formulaire, (HTMLInputElement
, HTMLSelectElement
, HTMLButtonElement
, HTMLOutputElement
ou HTMLTextAreaElement
). Dans ce cas, seules les contraintes de l'élément correspondant sont évaluées et permettent au script d'obtenir l'état de validité. La méthode checkValidity()
renvoie un booléen qui indique si la valeur de l'élément respecte les contraintes (c'est généralement ce qui est fait par l'agent utilisateur pour déterminer quelle pseudo-classe CSS s'applique entre :valid
et :invalid
). La méthode reportValidity()
renvoie quant à elle le détail des contraintes qui ne sont pas respectées.checkValidity()
ou reportValidity()
de l'objet HTMLFormElement
correspondant au formulaire.On qualifie parfois un appel à checkValidity()
de validation statique des contraintes, en opposition à reportValidity()
ou à l'envoi du formulaire qui constituent une validation interactive.
Note :
novalidate
est placé sur l'élément <form>
, la validation interactive des contraintes n'a pas lieu.submit()
d'un objet HTMLFormElement
ne déclenchera pas de validation des contraintes. Autrement dit, cette méthode envoie les données du formulaire au serveur, même si elles ne respectent pas les contraintes. Pour passer par la validation, on pourra appeler la méthode click()
du bouton d'envoi.Grâce à JavaScript et à l'API Constraint Validation, on peut implémenter des contraintes plus complexes, qui portent par exemple sur plusieurs champs à la fois ou qui impliquent des calculs avancés.
Le principe consiste à déclencher une fonction JavaScript lorsqu'un évènement d'un champ de formulaire a lieu (par exemple change
) et de calculer à ce moment si la contrainte est respectée ou non puis d'utiliser field.setCustomValidity()
pour fournir le résultat de la validation : une chaîne vide indiquera que la contrainte est respectée et n'importe quelle autre chaîne indiquera une erreur et c'est alors cette chaîne de caractères qui sera affichée à l'utilisatrice ou à l'utilisateur.
Le format utilisé pour les codes postaux varie d'un pays à l'autre. Certains pays autorisent un préfixe avec le code du pays (comme D-
en Allemagne, F-
en France, etc.), d'autres ont des codes postaux avec un nombre précis de chiffres et d'autres encore, comme au Royaume-Uni, ont des structures plus complexes, où on peut avoir des lettres à certaines positions.
Note : Ce qui suit ne constitue pas une bibliothèque exhaustive de validation des codes postaux, il ne s'agit que d'un exemple.
Pour cet exemple, nous allons ajouter un script de vérification pour ce formulaire :
<form>
<label for="ZIP">Code postal : </label>
<input type="text" id="ZIP" />
<label for="Country">Pays : </label>
<select id="Country">
<option value="ch">Suisse</option>
<option value="fr">France</option>
<option value="de">Allemagne</option>
<option value="nl">Pays-Bas</option>
</select>
<input type="submit" value="Valider" />
</form>
Ce fragment HTML affiche le formulaire suivant :
Pour commencer, on écrit une fonction qui vérifie la contrainte :
function checkZIP() {
// Pour chaque pays, on définit le motif que doit suivre le code
const constraints = {
ch: [
"^(CH-)?\\d{4}$",
"Les codes postaux suisses ont 4 chiffres : par exemple CH-1950 ou 1950",
],
fr: [
"^(F-)?\\d{5}$",
"Les codes postaux français ont 5 chiffres : par exemple F-75012 ou 75012",
],
de: [
"^(D-)?\\d{5}$",
"Les codes postaux allemands ont 5 chiffres : par exemple D-12345 ou 12345",
],
nl: [
"^(NL-)?\\d{4}\\s*([A-RT-Z][A-Z]|S[BCE-RT-Z])$",
"Les codes postaux néerlandais ont 4 chiffres, suivi par deux lettres sauf SA, SD et SS",
],
};
// On récupère l'identifiant du pays
const country = document.getElementById("Country").value;
// On récupère le champ du code postal
const ZIPField = document.getElementById("ZIP");
// On construit le validateur pour la contrainte
const constraint = new RegExp(constraints[country][0], "");
console.log(constraint);
// On vérifie la valeur par rapport à la contrainte !
if (constraint.test(ZIPField.value)) {
// Le code postal respecte la contrainte, on communique ce résultat via l'API
ZIPField.setCustomValidity("");
} else {
// Le code postal ne respecte pas la contrainte, on envoie un message
// via l'API pour fournir des informations sur le format attendu
ZIPField.setCustomValidity(constraints[country][1]);
}
}
Ensuite, on ajoute des gestionnaires d'évènements pour l'évènement change
du champ <select>
et pour l'évènement input
de l'élément <input>
:
window.onload = () => {
const countrySelect = document.getElementById("Country");
const zipInput = document.getElementById("ZIP");
countrySelect.addEventListener("change", checkZIP);
zipInput.addEventListener("input", checkZIP);
};
Limiter la taille d'un fichier avant son envoi
Une autre contrainte fréquemment rencontrée consiste à appliquer une limite sur la taille d'un fichier à téléverser. Pour vérifier cela côté client avant d'envoyer le fichier, nous allons combiner l'API Constraint Validation (notamment la méthode field.setCustomValidity()
), avec une autre API, l'API File.
Voici le fragment HTML utilisé pour l'exemple :
<label for="FS">Veuillez choisir un fichier qui ne dépasse pas 75ko : </label>
<input type="file" id="FS" />
Cela donnera le formulaire suivant :
Pour le code JavaScript, on lit le fichier sélectionné avec la méthode File.size()
pour obtenir sa taille et on compare cette valeur avec la limite (ici codée en dur), puis on appelle l'API de validation pour indiquer au navigateur si la contrainte est respectée :
function checkFileSize() {
const FS = document.getElementById("FS");
const files = FS.files;
// S'il y a (au moins) un fichier sélectionné
if (files.length > 0) {
if (files[0].size > 75 * 1024) {
// La contrainte n'est pas respectée
FS.setCustomValidity("Le fichier sélectionné ne doit pas dépasser 75ko.");
return;
}
}
// La contrainte spécifique est bien respectée
FS.setCustomValidity("");
}
Pour finir, on attache cette méthode au gestionnaire d'évènement correspondant :
window.onload = () => {
const fsInput = document.getElementById("FS");
fsInput.addEventListener("change", checkFileSize);
};
Mise en forme visuelle pour la validation des contraintes
En plus de définir des contraintes, lors du développement, on voudra contrôler la façon dont les contraintes sont communiquées aux utilisatrices et utilisateurs : quels messages sont utilisés et quelle mise en forme est appliquée pour les champs valides/invalides.
Contrôler l'aspect des élémentsL'aspect des éléments peut être personnalisé grâce aux pseudo-classes CSS suivantes.
:required
et :optional
Les pseudo-classes :required
et :optional
permettent d'écrire des sélecteurs pour cibler les éléments qui ont ou non l'attribut required
.
:placeholder-shown
Voir :placeholder-shown
.
:valid
et :invalid
Les pseudo-classes :valid
et :invalid
sont utilisées pour représenter des éléments <input>
dont le contenu est valide (respectivement invalide) par rapport au type de champ. Ces classes permettent de mettre en forme les éléments de formulaire valides ou invalides afin d'en faciliter l'identification.
Plusieurs outils peuvent vous aider à contrôler le texte utilisé pour indiquer une erreur de validation :
La méthode setCustomValidity(message)
pour les éléments suivants :
<fieldset>
. Note : fournir un message d'invalidité personnalisé pour les éléments <fieldset>
n'empêchera pas l'envoi du formulaire dans la plupart des navigateurs.<input>
<output>
<select>
<button>
de type submit
ou avec un élément <input>
de type submit
. Les autres types de bouton ne contribuent pas à la validation des contraintes.)<textarea>
L'interface ValidityState
décrit l'objet renvoyé par la propriété validity
des types d'éléments listés ci-avant. Elle représente différentes façons selon lesquelles une valeur saisie peut être invalide. Avec la méthode précédente, elle permet d'expliquer la raison pour laquelle la valeur d'un champ est invalide.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4