Le guide complet des formulaires HTML et de la validation des contraintes

Dans cet article, nous examinons les champs de formulaire HTML et les options de validation offertes par HTML5. Nous verrons également comment ces dernières peuvent être améliorées grâce à l’utilisation de CSS et de JavaScript.

Qu’est-ce que la Validation par Contraintes?

Chaque champ de formulaire a un but. Et ce but est souvent régi par contraintes — ou les règles gouvernant ce qui doit et ne doit pas être entré dans chaque champ de formulaire. Par exemple, un champ email nécessitera une adresse email valide; un champ password pourrait exiger certains types de caractères et avoir un nombre minimum de caractères requis; et un champ de texte pourrait avoir une limite sur le nombre de caractères pouvant être entrés.

Les navigateurs modernes ont la capacité de vérifier que ces contraintes sont respectées par les utilisateurs et peuvent les avertir lorsque ces règles ont été enfreintes. Cela s’appelle la validation par contraintes.

Validation côté client vs côté serveur

La plupart du code JavaScript écrit dans les premières années du langage traitait de la validation côté client des formulaires. Même aujourd’hui, les développeurs passent beaucoup de temps à écrire des fonctions pour vérifier les valeurs des champs. Est-ce encore nécessaire dans les navigateurs modernes? Probablement pas. Dans la plupart des cas, cela dépend vraiment de ce que vous essayez de faire.

Mais d’abord, voici un gros message d’avertissement:

La validation côté client est une commodité qui peut empêcher les erreurs courantes d’entrée de données avant qu’une application ne perde du temps et de la bande passante en envoyant des données à un serveur. Ce n’est pas un substitut à la validation côté serveur!

Toujours nettoyer les données côté serveur. Toutes les requêtes ne proviennent pas d’un navigateur. Même quand c’est le cas, il n’y a aucune garantie que le navigateur ait validé les données. Quiconque sait comment ouvrir les outils de développement d’un navigateur peut également contourner votre bien pensé HTML et JavaScript.

Champs de saisie HTML5

HTML propose :

Mais vous utiliserez le plus souvent <input>:

<input type="text" name="username" />

L’attribut type définit le type de contrôle, et il existe un large choix d’options:

type description
button a button with no default behavior
checkbox a check/tick box
color a color picker
date a date picker for the year, month, and day
datetime-local a date and time picker
email an email entry field
file a file picker
hidden a hidden field
image a button which displays the image defined by the src attribute
month a month and year picker
number a number entry field
password a password entry field with obscured text
radio a radio button
range a slider control
reset a button that resets all form inputs to their default values (but avoid using this, as it’s rarely useful)
search a search entry field
submit a form submission button
tel a telephone number entry field
text a text entry field
time a time picker with no time zone
url a URL entry field
week a week number and year picker

Le navigateur retombe sur text si vous omettez l’attribut type ou s’il ne prend pas en charge une option. Les navigateurs modernes ont une bonne prise en charge de tous les types, mais les anciens navigateurs afficheront toujours un champ d’entrée de texte.

D’autres attributs utiles de <input> incluent:

attribute description
accept file upload type
alt alternative text for the image types
autocomplete hint for field auto-completion
autofocus focus field on page load
capture media capture input method
checked checkbox/radio is checked
disabled disable the control (it won’t be validated or have its value submitted)
form associate with a form using this ID
formaction URL for submission on submit and image buttons
inputmode data type hint
list ID of <datalist> autocomplete options
max maximum value
maxlength maximum string length
min minimum value
minlength minimum string length
name name of control, as submitted to server
pattern a regular expression pattern, such as [A-Z]+ for one or more uppercase characters
placeholder placeholder text when the field value is empty
readonly the field is not editable, but it will still be validated and submitted
required the field is required
size the size of the control (often overridden in CSS)
spellcheck set true or false spell-checking
src image URL
step incremental values in numbers and ranges
type field type (see above)
value the initial value

Champs de sortie HTML

En plus des types d’entrée, HTML5 fournit des sorties en lecture seule :

  • output: le résultat textuel d’un calcul ou d’une action de l’utilisateur
  • progress: une barre de progression avec les attributs value et max
  • meter: une échelle qui peut varier entre vert, ambre et rouge en fonction des valeurs définies pour les attributs value, min, max, low, high et optimum.

Labels d’entrée

Les champs doivent avoir un <label> associé, que vous pouvez entourer l’élément :

<label>your name <input type="text" name="name" /><label>

Ou lier le champ à l’étiquette en utilisant un attribut for :

<label for="nameid">your name</label>
<input type="text" id="nameid" name="name" />

Les étiquettes sont importantes pour l’accessibilité. Vous avez peut-être rencontré des formulaires qui utilisent un placeholder pour économiser de l’espace à l’écran :

<input type="text" name="name" value="" placeholder="your name" />

Le texte du placeholder disparaît une fois que l’utilisateur tape quelque chose – même un seul espace. Il est préférable de montrer une étiquette plutôt que de forcer l’utilisateur à se souvenir de ce que le champ demandait !

Comportements d’entrée

Les types de champs et les attributs de contrainte modifient le comportement d’entrée du navigateur. Par exemple, une entrée number affiche un clavier numérique sur les appareils mobiles. Le champ peut afficher un curseur de retournement et les pressions de clavier haut/bas incrémenteront et décrémenteront les valeurs.

La plupart des types de champs sont évidents, mais il y a des exceptions. Par exemple, les cartes de crédit sont numériques, mais le spinner de décrément/incrément est inutile et il est trop facile de presser vers le haut ou vers le bas lors de la saisie d’un numéro à 16 chiffres. Il est préférable d’utiliser un type texte standard, mais de définir l’attribut inputmode sur numérique, ce qui affiche un clavier approprié. La configuration de autocomplete="cc-number" suggère également toutes les cartes de crédit préconfigurées ou précédemment entrées.

L’utilisation du bon type de champ type et autocorrect offre des avantages qui seraient difficiles à obtenir en JavaScript. Par exemple, certains navigateurs mobiles peuvent :

Validation automatique

Le navigateur garantit qu’une valeur d’entrée respecte les contraintes définies par les attributs type, min, max, step, minlength, maxlength, pattern et required. Par exemple :

<input type="number" min="1" max="100" required />

Tentative de soumission d’une valeur vide empêche la soumission du formulaire et affiche le message suivant dans Chrome :

Les curseurs ne permettront pas de valeurs en dehors de la plage de 1 à 100. Des messages de validation similaires apparaissent si vous tapez une chaîne qui n’est pas un nombre. Tout cela sans une seule ligne de JavaScript.

Vous pouvez arrêter la validation du navigateur en :

  • ajoutant un attribut novalidate à l’élément <form>
  • ajoutant un attribut formnovalidate à un bouton de soumission ou à une image

Création d’entrées JavaScript personnalisées

Si vous écrivez un composant d’entrée de date basé sur JavaScript, arrêtez-vous et éloignez-vous de votre clavier !

Écrire des contrôles d’entrée personnalisés est difficile. Vous devez prendre en compte la souris, le clavier, le tactile, la parole, l’accessibilité, les dimensions de l’écran et ce qui se passe lorsque JavaScript échoue. Vous créez également une expérience utilisateur différente. Peut-être que votre contrôle est supérieur au sélecteur de date standard sur desktop, iOS et Android, mais l’interface utilisateur inconnue confondra certains utilisateurs.

Il y a trois raisons principales pour lesquelles les développeurs choisissent de créer des entrées basées sur JavaScript.

1. Les contrôles standard sont difficiles à styliser

Le style CSS est limité et nécessite souvent des astuces, telles que l’ajout d’un input avec les pseudo-éléments ::before et ::after de son étiquette. La situation s’améliore, mais interrogez toute conception qui privilégie la forme sur la fonction.

2. Les types modernes de <input> ne sont pas pris en charge dans les anciens navigateurs

En substance, vous codez pour Internet Explorer. Les utilisateurs d’IE n’obtiendront pas un sélecteur de date mais peuvent toujours saisir des dates au format AAAA-MM-JJ. Si votre client insiste, chargez un polyfill uniquement dans IE. Il n’est pas nécessaire de surcharger les navigateurs modernes.

3. Vous avez besoin d’un nouveau type d’entrée qui n’a jamais été implémenté auparavant

Ces situations sont rares, mais commencez toujours avec des champs HTML5 appropriés. Ils sont rapides et fonctionnent même avant que le script ne soit chargé. Vous pouvez améliorer progressivement les champs au besoin. Par exemple, un peu de JavaScript peut s’assurer qu’une date de fin d’événement de calendrier survient après une date de début.

En résumé : évitez de réinventer les contrôles HTML !

Style de Validation CSS

Vous pouvez appliquer les pseudo-classes suivantes aux champs d’entrée pour les styliser en fonction de l’état actuel :

selector description
:focus the field with focus
:focus-within an element contains a field with focus (yes, it’s a parent selector!)
:focus-visible an element has focus owing to keyboard navigation, so a focus ring or more evident styling is necessary
:required a field with a required attribute
:optional a field without a required attribute
:valid a field that has passed validation
:invalid a field that has not passed validation
:user-valid a field that has passed validation after the user has interacted with it (Firefox only)
:user-invalid a field that hasn’t passed validation after the user has interacted with it (Firefox only)
:in-range the value is within range on a number or range input
:out-of-range the value is out of range on a number or range input
:disabled a field with a disabled attribute
:enabled a field without a disabled attribute
:read-only a field with a read-only attribute
:read-write: a field without a read-only attribute
:checked a checked checkbox or radio button
:indeterminate an indeterminate checkbox or radio state, such as when all radio buttons are unchecked
:default the default submit button or image

Vous pouvez styliser le texte placeholder d’un champ d’entrée avec le pseudo-élément ::placeholder :

/* placeholer bleu sur les champs email */
input[type="email"]::placeholder {
  color: blue;
}

Les sélecteurs ci-dessus ont la même spécificité, donc l’ordre peut être important. Considérez cet exemple :

input:invalid { color: red; }
input:enabled { color: black; }

Les entrées invalides ont un texte rouge, mais cela n’est appliqué qu’aux entrées avec un attribut disableddonc toutes les entrées activées sont en noir.

Le navigateur applique les styles de validation au chargement de la page. Par exemple, dans le code suivant, chaque champ invalide reçoit une bordure rouge :

:invalid {
  border-color: #900;
}

L’utilisateur est confronté à un ensemble intimidant de boîtes rouges avant d’interagir avec le formulaire. Afficher les erreurs de validation après la première soumission ou lorsqu’une valeur est modifiée offrira une meilleure expérience. C’est là que JavaScript intervient…

JavaScript et l’API de Validation des Contraintes

La API de Validation des Contraintes offre des options de personnalisation du formulaire qui peuvent améliorer le contrôle des champs HTML de base. Vous pourriez :

  • arrêter la validation jusqu’à ce que l’utilisateur interagisse avec un champ ou soumette le formulaire
  • afficher des messages d’erreur avec un style personnalisé
  • fournir une validation personnalisée qui est impossible en HTML seul. C’est souvent nécessaire lorsque vous devez comparer deux entrées — comme lorsque vous entrez une adresse e-mail ou un numéro de téléphone, vérifiez que les champs « nouveau » et « confirmer » de mot de passe ont la même valeur, ou assurez-vous qu’une date vient après une autre.

Validation du Formulaire

Avant d’utiliser l’API, votre code devrait désactiver la validation par défaut et les messages d’erreur en définissant la propriété noValidate du formulaire sur true (le même effet que l’ajout d’un attribut novalidate) :

const myform = document.getElementById('myform');
myform.noValidate = true;

Vous pouvez ensuite ajouter des gestionnaires d’événements — comme lorsque le formulaire est soumis :

myform.addEventListener('submit', validateForm);

Le gestionnaire peut vérifier que tout le formulaire est valide en utilisant les méthodes checkValidity() ou reportValidity(), qui renvoient true lorsque tous les inputs du formulaire sont valides. (La différence est que checkValidity() vérifie si des inputs sont soumis à la validation des contraintes.)

Les documents Mozilla expliquent:

Un événement invalid est également déclenché sur chaque champ invalide. Cela ne remonte pas : les gestionnaires doivent être ajoutés à chaque contrôle qui l’utilise.

// valider le formulaire à la soumission
function validateForm(e) {

  const form = e.target;

  if (form.checkValidity()) {

    // le formulaire est valide - faire d'autres vérifications

  }
  else {

    // le formulaire est invalide - annuler la soumission
    e.preventDefault();

  }

};

A valid form could now incur further validation checks. Similarly, an invalid form could have invalid fields highlighted.

Validation des champs

Les champs individuels ont les propriétés de validation des contraintes suivantes :

  • willValidate : renvoie true si l’élément est candidat à la validation des contraintes.

  • validationMessage : le message de validation. Ce sera une chaîne vide si le champ est valide.

  • valitity: un objet ValidityState. Cela a une propriété valid définie sur true lorsque le champ est valide. Si elle est false, l’une ou plusieurs des propriétés suivantes seront true:

    ValidityState description
    .badInput le navigateur ne peut pas comprendre l’entrée
    .customError un message de validité personnalisé a été défini
    .patternMismatch la valeur ne correspond pas à l’attribut pattern spécifié
    .rangeOverflow la valeur est supérieure à l’attribut max
    .rangeUnderflow la valeur est inférieure à l’attribut min
    .stepMismatch la valeur ne respecte pas les règles de l’attribut step
    .tooLong la longueur de la chaîne est supérieure à l’attribut maxlength
    .tooShort la longueur de la chaîne est inférieure à l’attribut minlength
    .typeMismatch la valeur n’est pas un email ou une URL valide
    .valueMissing une valeur requise est vide

Les champs individuels ont les méthodes de validation des contraintes suivantes:

  • setCustomValidity(message): définit un message d’erreur pour un champ invalide. Un message vide doit être passé lorsque le champ est valide, sinon le champ restera invalide indéfiniment.
  • checkValidity(): renvoie true si l’entrée est valide. La propriété valitity.valid fait la même chose, mais checkValidity() déclenche également un événement invalid sur le champ, ce qui pourrait être utile.

La fonction de gestionnaire validateForm() pourrait parcourir chaque champ et appliquer une classe invalid à son élément parent le cas échéant:

function validateForm(e) {
  const form = e.target;
  if (form.checkValidity()) {
    // le formulaire est valide - effectuer d'autres vérifications
  }
  else {
    // le formulaire est invalide - annuler la soumission
    e.preventDefault();
    // appliquer la classe invalide
    Array.from(form.elements).forEach(i => {
      if (i.checkValidity()) {
        // le champ est valide - supprimer la classe
        i.parentElement.classList.remove('invalid');
      }
      else {
        // le champ est invalide - ajouter la classe
        i.parentElement.classList.add('invalid');
      }
    });
  }
};

Supposons que votre HTML ait défini un champ email :

<div>
  <label for="email">email</label>
  <input type="email" id="email" name="email" required />
  <p class="help">Please enter a valid email address</p>
</div>

Le script applique une classe invalid au <div> lorsque l’email n’est pas spécifié ou est invalide. Le CSS peut afficher ou masquer le message de validation lorsque le formulaire est soumis :

.help { display: none; }
.invalid .help { display: block; }
.invalid label, .invalid input, .invalid .help {
  color: red;
  border-color: red;
}

Création d’un validateur de formulaire personnalisé

La démonstration suivante présente un exemple de formulaire de contact qui nécessite un nom d’utilisateur et soit une adresse e-mail, un numéro de téléphone, ou les deux :

Il est mis en œuvre à l’aide d’une classe de validation de formulaire générique appelée FormValidate. Un élément de formulaire est transmis lors de l’instanciation d’un objet. Un deuxième paramètre optionnel peut être défini :

  • true pour valider chaque champ au fur et à mesure que l’utilisateur interagit avec lui
  • false (par défaut) pour valider tous les champs après le premier envoi (la validation au niveau du champ se produit après cela)
// valider le formulaire de contact
const contactForm = new FormValidate(document.getElementById('contact'), false);

Une méthode .addCustom(field, func) définit des fonctions de validation personnalisées. Le code suivant garantit que soit le champ email soit le champ tel sont valides (aucun n’a d’attribut required) :

// validation personnalisée - email et/ou téléphone
const
  email = document.getElementById('email'),
  tel = document.getElementById('tel');

contactForm.addCustom(email, f => f.value || tel.value);
contactForm.addCustom(tel, f => f.value || email.value);

A FormValidate object monitors both of the following:

  • Les événements focusout, qui vérifient ensuite un champ individuel
  • Les événements submit du formulaire, qui vérifient ensuite chaque champ

Les deux appellent la méthode .validateField(field), qui vérifie si un champ réussit la validation de contrainte standard. Lorsqu’il le fait, toutes les fonctions de validation personnalisées attribuées à ce champ s’exécutent à leur tour. Toutes doivent renvoyer true pour que le champ soit valide.

Les champs invalides ont une classe invalid appliquée à l’élément parent du champ, qui affiche un message d’aide rouge à l’aide de CSS.

Enfin, l’objet appelle une fonction personnalisée submit lorsque tout le formulaire est valide:

// soumission personnalisée
contactForm.submit = e => {
  e.preventDefault();
  alert('Form is valid!\n(open the console)');
  const fd = new FormData(e.target);
  for (const [name, value] of fd.entries()) {
    console.log(name + ': ' + value);
  }
}

Alternativement, vous pouvez utiliser un addEventListener standard pour gérer les événements submit du formulaire, car FormValidate empêche l’exécution d’autres gestionnaires lorsque le formulaire est invalide.

Form Finesse

Les formulaires sont la base de tous les applications web et les développeurs passent beaucoup de temps à manipuler les entrées utilisateur. La validation des contraintes est bien prise en charge : les navigateurs peuvent gérer la plupart des vérifications et afficher des options d’entrée appropriées.

Recommandations:

  • Utilisez les types d’entrée HTML standard lorsque c’est possible. Définissez les attributs min, max, step, minlength, maxlength, pattern, required, inputmode, et autocomplete comme il convient.
  • Si nécessaire, utilisez un peu de JavaScript pour activer la validation et les messages personnalisés.
  • Pour les champs plus complexes, améliorez progressivement les entrées standard.

Enfin : oubliez Internet Explorer !

À moins que vos clients ne soient principalement des utilisateurs d’IE, il n’est pas nécessaire d’implémenter vos propres fonctions de validation de secours. Tous les champs d’entrée HTML5 fonctionnent dans IE mais peuvent nécessiter plus d’effort de la part de l’utilisateur. (Par exemple, IE ne détecte pas quand vous entrez une adresse e-mail invalide.) Vous devez toujours valider les données côté serveur, alors envisagez d’utiliser cela comme base du contrôle des erreurs IE.

Foire aux questions (FAQ) sur les formulaires HTML et la validation des contraintes

Quelle est l’importance de la validation des formulaires HTML?

La validation des formulaires HTML est un aspect crucial du développement web. Elle garantit que les données entrées par les utilisateurs dans un formulaire respectent certains critères avant d’être envoyées au serveur. Cela non seulement maintient l’intégrité des données, mais améliore également l’expérience utilisateur en fournissant un retour immédiat sur la correction des données entrées. Sans validation des formulaires, il existe un risque de recevoir des données incorrectes, incomplètes ou même malveillantes, ce qui peut entraîner diverses problèmes, y compris la corruption des données, les violations de sécurité et les plantages du système.

Comment HTML5 améliore-t-il la validation des formulaires?

HTML5 introduit plusieurs nouveaux éléments et attributs de formulaire qui facilitent et rendent beaucoup plus efficace la validation des formulaires. Par exemple, il fournit de nouveaux types d’entrée tels que email, URL et nombre, qui valident automatiquement les données d’entrée en fonction du type. Il introduit également de nouveaux attributs comme required, pattern, et min/max qui vous permettent de spécifier diverses contraintes sur les données d’entrée. De plus, HTML5 fournit une API de validation intégrée qui vous permet de réaliser une validation personnalisée à l’aide de JavaScript.

Puis-je effectuer la validation des formulaires sans JavaScript?

Oui, vous pouvez effectuer une validation de base des formulaires en utilisant uniquement HTML5. HTML5 fournit plusieurs nouveaux types d’entrée et attributs qui vous permettent de spécifier diverses contraintes sur les données d’entrée. Par exemple, vous pouvez utiliser l’attribut required pour rendre un champ obligatoire, l’attribut pattern pour appliquer un format spécifique, et les attributs min/max pour définir une plage pour les entrées numériques. Cependant, pour une validation plus complexe, vous pourriez toujours avoir besoin d’utiliser JavaScript.

Comment puis-je personnaliser les messages d’erreur dans la validation des formulaires HTML5?

HTML5 fournit une API de validation qui vous permet de personnaliser les messages d’erreur. Vous pouvez utiliser la méthode setCustomValidity de l’objet ValidityState pour définir un message d’erreur personnalisé pour un champ. Cette méthode prend un argument de chaîne, qui devient le message de validation du champ lorsque le champ est invalide. Vous pouvez appeler cette méthode en réponse à l’événement invalid, qui est déclenché lorsqu’un champ échoue à la validation.

Comment puis-je désactiver la validation des formulaires HTML5?

Vous pouvez désactiver la validation des formulaires HTML5 en ajoutant l’attribut novalidate à l’élément form. Lorsque cet attribut est présent, le navigateur ne procédera à aucune validation sur le formulaire lorsqu’il est soumis. Cela peut être utile si vous souhaitez gérer la validation entièrement côté serveur ou en utilisant un JavaScript personnalisé.

Comment puis-je valider plusieurs champs ensemble en HTML5?

HTML5 ne fournit pas de méthode intégrée pour valider plusieurs champs ensemble. Cependant, vous pouvez réaliser cela en utilisant JavaScript. Vous pouvez écrire une fonction de validation personnalisée qui vérifie les valeurs de plusieurs champs et définit un message de validité personnalisé s’ils ne répondent pas aux critères requis. Vous pouvez appeler cette fonction en réponse à l’événement de soumission du formulaire ou aux événements d’entrée/changement des champs.

Comment puis-je valider un champ en fonction de la valeur d’un autre champ en HTML5?

HTML5 ne fournit pas de méthode intégrée pour valider un champ en fonction de la valeur d’un autre champ. Cependant, vous pouvez réaliser cela en utilisant JavaScript. Vous pouvez écrire une fonction de validation personnalisée qui vérifie la valeur d’un champ par rapport à la valeur d’un autre champ et définit un message de validité personnalisé s’ils ne correspondent pas. Vous pouvez appeler cette fonction en réponse aux événements d’entrée/changement des champs.

Comment puis-je effectuer une validation asynchrone en HTML5?

HTML5 ne prend pas en charge la validation asynchrone en standard. Cependant, vous pouvez réaliser cela en utilisant JavaScript. Vous pouvez écrire une fonction de validation personnalisée qui effectue une opération asynchrone, telle qu’une requête AJAX, et définit un message de validité personnalisé en fonction du résultat. Vous pouvez appeler cette fonction en réponse aux événements d’entrée/changement des champs ou à l’événement de soumission du formulaire.

Comment puis-je styliser les messages d’erreur dans la validation de formulaire HTML5?

L’apparence des messages d’erreur dans la validation des formulaires HTML5 est déterminée par le navigateur et ne peut pas être directement stylisée à l’aide de CSS. Cependant, vous pouvez créer des messages d’erreur personnalisés à l’aide de JavaScript et les styliser comme vous le souhaitez. Vous pouvez utiliser l’API de validation pour déterminer quand un champ est invalide et afficher un message d’erreur personnalisé en conséquence.

Comment puis-je tester la validation d’un formulaire HTML?

Vous pouvez tester la validation d’un formulaire HTML en entrant divers types de données dans les champs et en essayant de soumettre le formulaire. Vous devriez tester avec des données valides et invalides pour vous assurer que la validation fonctionne correctement dans tous les cas. Vous pouvez également utiliser des outils ou des bibliothèques de test automatisés pour effectuer un test plus approfondi.

Source:
https://www.sitepoint.com/html-forms-constraint-validation-complete-guide/