Aller au contenu
BDU Cauri, accueilv0.1.0
Formulaires

Validation

Cauri affiche l’état valide ou invalide d’un champ et son message avec .is-valid, .is-invalid, .valid-feedback et .invalid-feedback. Elle fonctionne avec la validation native du navigateur, avec un contrôle côté serveur ou avec les deux.

Un champ validé reçoit une bordure colorée et une icône (coche verte pour valide, cercle d’exclamation rouge pour invalide). Le message d’accompagnement est un bloc .valid-feedback ou .invalid-feedback placé après le champ ; il n’est visible que si le champ est dans l’état correspondant.

La couleur ne suffit pas à transmettre l’état : écrivez toujours un message qui explique le problème et la façon de le corriger.

États valide et invalide#

Ajoutez .is-valid ou .is-invalid au champ. Reliez le message au champ avec aria-describedby pour qu’il soit lu en même temps.

Nom enregistré.
L'IBAN est incomplet : il comporte 28 caractères. Vérifiez-le sur le relevé du bénéficiaire.
Saisissez un montant supérieur ou égal à 1 000 FCFA.
<form>
  <div class="mb-3">
    <label for="valid-nom" class="form-label">Nom du titulaire</label>
    <input type="text" class="form-control is-valid" id="valid-nom" value="Aya Kouassi" autocomplete="name" aria-describedby="valid-nom-retour">
    <div id="valid-nom-retour" class="valid-feedback">Nom enregistré.</div>
  </div>
  <div class="mb-3">
    <label for="valid-iban" class="form-label">IBAN du bénéficiaire</label>
    <input type="text" class="form-control is-invalid" id="valid-iban" value="CI93 CI008 0111" autocomplete="off" aria-describedby="valid-iban-retour" aria-invalid="true">
    <div id="valid-iban-retour" class="invalid-feedback">L'IBAN est incomplet : il comporte 28 caractères. Vérifiez-le sur le relevé du bénéficiaire.</div>
  </div>
  <div class="mb-3">
    <label for="valid-montant" class="form-label">Montant du virement (FCFA)</label>
    <input type="text" class="form-control is-invalid" id="valid-montant" value="0" inputmode="numeric" aria-describedby="valid-montant-retour" aria-invalid="true">
    <div id="valid-montant-retour" class="invalid-feedback">Saisissez un montant supérieur ou égal à 1 000 FCFA.</div>
  </div>
</form>

Sélecteur, zone de texte, case et radio#

Tous les contrôles de formulaire acceptent les états. Pour une case ou un radio, placez le message après le libellé, dans le même .form-check.

Choisissez un type de compte pour continuer.
Le motif apparaîtra sur le relevé du bénéficiaire.
Cochez cette case pour ouvrir le compte.
Mode de livraison de la carte
Choisissez un mode de livraison.
<form>
  <div class="mb-3">
    <label for="valid-type" class="form-label">Type de compte</label>
    <select class="form-select is-invalid" id="valid-type" aria-describedby="valid-type-retour" aria-invalid="true">
      <option value="" selected>Choisir…</option>
      <option>Compte courant</option>
      <option>Compte d'épargne</option>
    </select>
    <div id="valid-type-retour" class="invalid-feedback">Choisissez un type de compte pour continuer.</div>
  </div>
  <div class="mb-3">
    <label for="valid-motif" class="form-label">Motif du virement</label>
    <textarea class="form-control is-valid" id="valid-motif" rows="2" aria-describedby="valid-motif-retour">Loyer du mois de mars</textarea>
    <div id="valid-motif-retour" class="valid-feedback">Le motif apparaîtra sur le relevé du bénéficiaire.</div>
  </div>
  <div class="form-check mb-3">
    <input class="form-check-input is-invalid" type="checkbox" id="valid-cgu" aria-describedby="valid-cgu-retour" aria-invalid="true">
    <label class="form-check-label" for="valid-cgu">J'accepte les conditions générales</label>
    <div id="valid-cgu-retour" class="invalid-feedback">Cochez cette case pour ouvrir le compte.</div>
  </div>
  <fieldset>
    <legend class="fs-6 fw-semibold">Mode de livraison de la carte</legend>
    <div class="form-check">
      <input class="form-check-input is-invalid" type="radio" name="valid-livraison" id="valid-liv-agence" aria-describedby="valid-liv-retour" aria-invalid="true">
      <label class="form-check-label" for="valid-liv-agence">Retrait en agence</label>
    </div>
    <div class="form-check mb-1">
      <input class="form-check-input is-invalid" type="radio" name="valid-livraison" id="valid-liv-domicile" aria-describedby="valid-liv-retour" aria-invalid="true">
      <label class="form-check-label" for="valid-liv-domicile">Livraison à domicile</label>
      <div id="valid-liv-retour" class="invalid-feedback">Choisissez un mode de livraison.</div>
    </div>
  </fieldset>
</form>

Validation native du navigateur#

Avec .was-validated sur le <form>, Cauri colore les champs selon les pseudo-classes :valid et :invalid et n’affiche que les messages des champs concernés. Les attributs required, type, pattern, min et maxlength définissent les règles. Ce formulaire est montré après une tentative d’envoi.

Saisissez une adresse e-mail valide, par exemple aya.kouassi@exemple.ci.
Saisissez 10 chiffres, avec ou sans espaces.
Numéro valide.
Choisissez votre pays de résidence.
Vous devez accepter les conditions pour continuer.
<form class="was-validated" novalidate>
  <div class="mb-3">
    <label for="natif-email" class="form-label">Adresse e-mail</label>
    <input type="email" class="form-control" id="natif-email" required autocomplete="email" aria-describedby="natif-email-retour">
    <div id="natif-email-retour" class="invalid-feedback">Saisissez une adresse e-mail valide, par exemple aya.kouassi@exemple.ci.</div>
  </div>
  <div class="mb-3">
    <label for="natif-tel" class="form-label">Téléphone mobile</label>
    <input type="tel" class="form-control" id="natif-tel" required pattern="[0-9 ]{10,14}" value="07 08 09 10 11" autocomplete="tel" aria-describedby="natif-tel-retour">
    <div id="natif-tel-retour" class="invalid-feedback">Saisissez 10 chiffres, avec ou sans espaces.</div>
    <div class="valid-feedback">Numéro valide.</div>
  </div>
  <div class="mb-3">
    <label for="natif-pays" class="form-label">Pays de résidence</label>
    <select class="form-select" id="natif-pays" required aria-describedby="natif-pays-retour">
      <option value="" selected>Choisir…</option>
      <option>Côte d'Ivoire</option>
    </select>
    <div id="natif-pays-retour" class="invalid-feedback">Choisissez votre pays de résidence.</div>
  </div>
  <div class="form-check mb-3">
    <input class="form-check-input" type="checkbox" id="natif-cgu" required aria-describedby="natif-cgu-retour">
    <label class="form-check-label" for="natif-cgu">J'accepte les conditions générales</label>
    <div id="natif-cgu-retour" class="invalid-feedback">Vous devez accepter les conditions pour continuer.</div>
  </div>
  <button class="btn btn-primary" type="button">Envoyer la demande</button>
</form>

Activer la validation native avec JavaScript#

Ajoutez novalidate au formulaire pour remplacer les bulles du navigateur par les messages de Cauri, puis posez .was-validated au premier envoi. Le script place aussi le focus sur le premier champ invalide, pour que le clavier et les lecteurs d’écran y arrivent directement.

document.querySelectorAll('form.needs-validation').forEach((formulaire) => {
  formulaire.addEventListener('submit', (evenement) => {
    if (!formulaire.checkValidity()) {
      evenement.preventDefault();
      evenement.stopPropagation();
      formulaire.querySelector(':invalid')?.focus();
    }
    formulaire.classList.add('was-validated');
  }, false);
});

Balisage du formulaire à valider#

La classe needs-validation n’a pas de style : elle sert seulement de repère au script ci-dessus.

<form class="needs-validation" novalidate>
  <label for="simulation-montant" class="form-label">Montant souhaité (FCFA)</label>
  <input type="number" class="form-control" id="simulation-montant"
         min="100000" max="10000000" step="50000" required
         aria-describedby="simulation-montant-retour">
  <div id="simulation-montant-retour" class="invalid-feedback">
    Saisissez un montant compris entre 100 000 et 10 000 000 FCFA.
  </div>
  <button class="btn btn-primary mt-3" type="submit">Lancer la simulation</button>
</form>

Validation côté serveur#

Quand le serveur renvoie des erreurs, posez vous-même .is-valid ou .is-invalid sur chaque champ et affichez le message reçu dans .invalid-feedback. Ne mettez pas .was-validated sur le formulaire. Gardez les valeurs saisies et ajoutez aria-invalid="true" aux champs en erreur.

Compte courant de Aya Kouassi.
Le solde disponible est de 1 250 000 FCFA. Réduisez le montant ou alimentez le compte.
<form>
  <div class="mb-3">
    <label for="serveur-compte" class="form-label">Numéro de compte à débiter</label>
    <input type="text" class="form-control is-valid" id="serveur-compte" value="01111 101111111111 36" aria-describedby="serveur-compte-retour">
    <div id="serveur-compte-retour" class="valid-feedback">Compte courant de Aya Kouassi.</div>
  </div>
  <div class="mb-3">
    <label for="serveur-montant" class="form-label">Montant (FCFA)</label>
    <input type="text" class="form-control is-invalid" id="serveur-montant" value="2 000 000" inputmode="numeric" aria-describedby="serveur-montant-retour" aria-invalid="true">
    <div id="serveur-montant-retour" class="invalid-feedback">Le solde disponible est de 1 250 000 FCFA. Réduisez le montant ou alimentez le compte.</div>
  </div>
  <button type="button" class="btn btn-primary">Valider le virement</button>
</form>

Validation dans un groupe de champs#

Le message de validation d’un .input-group peut casser l’arrondi des bords. Ajoutez .has-validation au groupe et placez le message en dernier enfant.

FCFA
Le montant doit être supérieur à zéro.
<div class="mb-3">
  <label for="valid-groupe-montant" class="form-label">Montant du virement</label>
  <div class="input-group has-validation">
    <input type="text" class="form-control is-invalid" id="valid-groupe-montant" value="0" inputmode="numeric" aria-describedby="valid-groupe-devise valid-groupe-retour" aria-invalid="true">
    <span class="input-group-text" id="valid-groupe-devise">FCFA</span>
    <div id="valid-groupe-retour" class="invalid-feedback">Le montant doit être supérieur à zéro.</div>
  </div>
</div>

Info-bulles de validation#

Remplacez .valid-feedback / .invalid-feedback par .valid-tooltip / .invalid-tooltip pour afficher le message dans une bulle flottante sous le champ. Le parent doit être en position: relative (.position-relative). Réservez les bulles aux formulaires où l’espace manque.

Nom enregistré.
Saisissez l'IBAN du bénéficiaire (28 caractères).
<form class="was-validated" novalidate>
  <div class="position-relative mb-4">
    <label for="bulle-nom" class="form-label">Nom complet</label>
    <input type="text" class="form-control" id="bulle-nom" value="Aya Kouassi" required aria-describedby="bulle-nom-retour">
    <div id="bulle-nom-retour" class="valid-tooltip">Nom enregistré.</div>
  </div>
  <div class="position-relative">
    <label for="bulle-iban" class="form-label">IBAN</label>
    <input type="text" class="form-control" id="bulle-iban" required aria-describedby="bulle-iban-retour">
    <div id="bulle-iban-retour" class="invalid-tooltip">Saisissez l'IBAN du bénéficiaire (28 caractères).</div>
  </div>
</form>

Classes de validation

Classes de validation
ClasseEffet
.is-validBordure verte et coche sur le champ ; affiche le message .valid-feedback ou .valid-tooltip qui suit.
.is-invalidBordure rouge et icône d’erreur sur le champ ; affiche .invalid-feedback ou .invalid-tooltip.
.was-validatedSur le <form> : applique les états selon :valid et :invalid pour tous les champs.
.valid-feedback, .invalid-feedbackMessage sous le champ, caché par défaut.
.valid-tooltip, .invalid-tooltipMessage en bulle flottante ; le parent doit être positionné.
.has-validationSur un .input-group : corrige les angles arrondis quand un message suit.

Variables Sass de validation

Redéfinissez ces variables avant d’importer Cauri (voir Sass) pour changer les couleurs ou désactiver les icônes.

Variables Sass de validation
VariableRôle
$form-feedback-valid-colorCouleur du texte et de la bordure de l’état valide (le vert de la marque par défaut).
$form-feedback-invalid-colorCouleur du texte et de la bordure de l’état invalide.
$form-feedback-icon-valid, $form-feedback-icon-invalidIcônes SVG affichées dans le champ.
$enable-validation-iconsMettre à false pour retirer les icônes des champs.
$form-validation-statesCarte des états : ajoutez-en un pour créer par exemple .is-warning.

Bonnes pratiques

À faire

  • Écrivez des messages qui disent comment corriger : « L’IBAN est incomplet : il comporte 28 caractères », pas « Champ invalide ».
  • Validez au moment de l’envoi, ou à la sortie du champ ; n’affichez pas d’erreur pendant la frappe.
  • Gardez les valeurs saisies après une erreur et replacez le focus sur le premier champ invalide.
  • Complétez toujours la validation du navigateur par un contrôle côté serveur : les règles du navigateur se contournent.

À éviter

  • Ne signalez pas une erreur par la couleur seule : le message écrit est obligatoire (la couleur et l’icône sont un complément).
  • N’affichez pas l’état valide partout : il alourdit le formulaire. Gardez-le pour les vérifications utiles (compte trouvé, code accepté).
  • N’utilisez pas les info-bulles de validation pour un message long : elles peuvent être coupées.
  • Ne bloquez pas l’envoi sans expliquer le motif.

Accessibilité

  • Reliez chaque message au champ avec aria-describedby et ajoutez aria-invalid="true" sur un champ en erreur.
  • Déplacez le focus sur le premier champ invalide ou sur un résumé des erreurs placé en tête de formulaire (role="alert").
  • Marquez les champs obligatoires avec required et une mention visible (« obligatoire »), pas avec un astérisque seul.
  • Gardez un contraste d’au moins 4,5:1 pour le texte des messages et vérifiez-le si vous personnalisez les couleurs de validation.
Charte provisoire, déduite du site public de la BDU CI. Elle sera remplacée par la charte officielle.