JavaScript : Manipulation des Formulaires
Valider, contrôler et exploiter les données saisies par l'utilisateur
Objectifs Pédagogiques
- Maîtriser la balise
<form>et ses attributs - Intercepter la soumission avec
preventDefault() - Lire tous les types de champs (texte, radio, checkbox, select, textarea)
- Valider les données côté client avant envoi
- Afficher des messages d'erreur ciblés par champ
- Utiliser les événements
focus,bluretsubmit - Activer/désactiver des champs dynamiquement
- Construire un formulaire complet avec validation en temps réel
Préparation du TP
1.1 Structure du projet
Créez un nouveau dossier TP4 dans votre dossier TP-JavaScript :
TP-JavaScript/
└── TP4/
├── index.html
├── style.css
└── script.js
1.2 Fichiers de départ
index.html<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>TP4 - Formulaires</title> <link rel="stylesheet" href="style.css"> </head> <body> <h1>TP4 — Manipulation des Formulaires</h1> <!-- Les sections seront ajoutées ici au fur et à mesure --> <script src="script.js"></script> </body> </html>
body {
font-family: Arial, sans-serif;
max-width: 650px;
margin: 40px auto;
padding: 20px;
}
h1 { text-align: center; margin-bottom: 30px; }
h2 { margin-top: 40px; margin-bottom: 16px; color: #1e40af; }
form {
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 8px;
padding: 24px;
margin-bottom: 24px;
}
label {
display: block;
font-weight: 600;
margin-bottom: 4px;
margin-top: 16px;
}
input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="tel"],
input[type="date"],
select,
textarea {
width: 100%;
padding: 10px 12px;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 6px;
margin-bottom: 4px;
}
input:focus, select:focus, textarea:focus {
outline: none;
border-color: #3b82f6;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
}
textarea { resize: vertical; min-height: 80px; }
button {
padding: 10px 24px;
font-size: 16px;
cursor: pointer;
border: none;
background: #1e40af;
color: white;
border-radius: 6px;
margin-top: 16px;
}
button:hover { background: #1d4ed8; }
.erreur {
color: #dc2626;
font-size: 0.875rem;
min-height: 20px;
}
.input-erreur {
border-color: #dc2626 !important;
box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1) !important;
}
.input-valide {
border-color: #059669 !important;
box-shadow: 0 0 0 3px rgba(5, 150, 105, 0.1) !important;
}
.resultat {
margin-top: 20px;
padding: 16px;
background: #f0f9ff;
border-radius: 8px;
font-size: 16px;
}
.groupe-radio label,
.groupe-checkbox label {
display: inline;
font-weight: normal;
margin-left: 4px;
margin-right: 16px;
}
.groupe-radio, .groupe-checkbox {
margin: 8px 0;
}
console.log("TP4 chargé avec succès");
Créez ces 3 fichiers, lancez index.html avec Live Server, et vérifiez que le message apparaît dans la console (F12).
La Balise <form> et la Soumission
2.1 Pourquoi utiliser <form> ?
Au TP3, on plaçait des <input> et des <button> directement dans la page. Ça fonctionne, mais dans un vrai site, on regroupe toujours les champs dans une balise <form>.
Analogie simple
Un <form>, c'est comme un formulaire papier (inscription, commande, enquête). Il regroupe tous les champs dans un même bloc et définit ce qui se passe quand on valide : où envoyer les données, comment les envoyer.
Sans <form>, vos champs sont comme des feuilles volantes. Avec <form>, ils font partie d'un même dossier.
Les avantages concrets de <form> :
- La touche Entrée soumet automatiquement le formulaire
- L'événement
"submit"permet d'intercepter la soumission - Les attributs HTML de validation (
required,minlength...) ne fonctionnent qu'à l'intérieur d'un<form> - L'accessibilité est meilleure (lecteurs d'écran, navigation au clavier)
2.2 Structure de base d'un formulaire
Ajoutez ce code dans votre index.html :
<h2>Formulaire de contact</h2> <form id="formContact"> <label for="nom">Nom :</label> <input type="text" id="nom" name="nom" placeholder="Votre nom"> <label for="email">Email :</label> <input type="email" id="email" name="email" placeholder="votre@email.com"> <label for="message">Message :</label> <textarea id="message" name="message" placeholder="Votre message..."></textarea> <button type="submit">Envoyer</button> </form> <div id="resultatContact" class="resultat" style="display:none;"></div>
L'attribut for du label
Le for="nom" dans le <label> doit correspondre à l'id="nom" de l'input. Cela permet de cliquer sur le texte du label pour activer le champ — c'est une bonne pratique d'accessibilité.
Attention au type du bouton
Dans un <form>, un <button> sans attribut type se comporte par défaut comme type="submit". Il est recommandé de toujours préciser le type :
type="submit"— soumet le formulairetype="button"— bouton simple, ne soumet pas le formulairetype="reset"— remet tous les champs à leur valeur initiale
2.3 Intercepter la soumission avec preventDefault()
Si vous cliquez sur « Envoyer » maintenant, la page se recharge. C'est le comportement par défaut du navigateur : il essaie d'envoyer les données à un serveur. Comme on n'a pas de serveur, on doit empêcher ce comportement pour traiter les données en JavaScript.
script.js// 1. Sélectionner le formulaire (pas le bouton !) let formContact = document.querySelector("#formContact"); // 2. Écouter l'événement "submit" sur le formulaire function gererSoumission(event) { // Empêcher le rechargement de la page event.preventDefault(); // Maintenant, on peut traiter les données ici console.log("Formulaire intercepté !"); } // 3. Associer formContact.addEventListener("submit", gererSoumission);
Comprendre le paramètre event
Quand un événement se déclenche, le navigateur passe automatiquement un objet event à votre fonction. Cet objet contient des informations sur l'événement (quel élément a été cliqué, quelle touche a été pressée, etc.).
La méthode event.preventDefault() dit au navigateur : « Ne fais pas ton action par défaut » (ici : ne recharge pas la page).
Testez le code. Cliquez sur « Envoyer » : la page ne doit plus se recharger. Le message doit apparaître dans la console. Testez aussi en appuyant sur Entrée dans un champ — le comportement doit être le même.
2.4 Lire les valeurs et afficher le résultat
Complétons la fonction pour lire les valeurs saisies et les afficher :
script.js (remplacer la fonction)let formContact = document.querySelector("#formContact"); let resultatContact = document.querySelector("#resultatContact"); function gererSoumission(event) { event.preventDefault(); // Lire les valeurs des champs let nom = document.querySelector("#nom").value; let email = document.querySelector("#email").value; let message = document.querySelector("#message").value; // Afficher les données récupérées resultatContact.style.display = "block"; resultatContact.innerHTML = ` <strong>Données reçues :</strong><br> Nom : ${nom}<br> Email : ${email}<br> Message : ${message} `; } formContact.addEventListener("submit", gererSoumission);
Résultat
Quand l'utilisateur remplit le formulaire et clique sur « Envoyer », les données saisies s'affichent en dessous — sans rechargement de la page.
Testez le formulaire. Remplissez les trois champs et soumettez. Vérifiez que les données s'affichent correctement en dessous.
Lire Tous les Types de Champs
3.1 Récapitulatif des types d'input
HTML propose de nombreux types de champs. Voici ceux que vous rencontrerez le plus souvent :
| Type | Affichage | Lecture en JS |
|---|---|---|
text |
Champ texte libre | .value → chaîne |
email |
Champ avec validation email | .value → chaîne |
password |
Champ masqué (points) | .value → chaîne |
number |
Champ numérique | Number(.value) → nombre |
date |
Sélecteur de date | .value → "2026-03-31" |
tel |
Champ téléphone | .value → chaîne |
checkbox |
Case à cocher | .checked → true/false |
radio |
Bouton radio (choix unique) | .checked → true/false |
Règle importante
Retenez la distinction :
.value→ pour les champs texte (text, email, password, number, date, tel, select, textarea).checked→ pour les champs à cocher (checkbox, radio)
3.2 Lire les boutons radio
Les boutons radio permettent de choisir une seule option parmi un groupe. Tous les radio d'un même groupe doivent avoir le même attribut name.
<h2>Choix du genre</h2> <form id="formGenre"> <p><strong>Genre :</strong></p> <div class="groupe-radio"> <input type="radio" id="homme" name="genre" value="Homme"> <label for="homme">Homme</label> <input type="radio" id="femme" name="genre" value="Femme"> <label for="femme">Femme</label> </div> <button type="submit">Valider</button> </form> <div id="resultatGenre" class="resultat" style="display:none;"></div>
let formGenre = document.querySelector("#formGenre"); let resultatGenre = document.querySelector("#resultatGenre"); function gererGenre(event) { event.preventDefault(); // Sélectionner le radio coché dans le groupe "genre" let radioSelectionne = document.querySelector('input[name="genre"]:checked'); if (radioSelectionne === null) { resultatGenre.textContent = "Veuillez sélectionner un genre."; resultatGenre.style.display = "block"; resultatGenre.style.color = "red"; return; } resultatGenre.textContent = `Genre choisi : ${radioSelectionne.value}`; resultatGenre.style.display = "block"; resultatGenre.style.color = "#333"; } formGenre.addEventListener("submit", gererGenre);
Décryptage du sélecteur CSS
input[name="genre"]:checked signifie : « un <input> dont l'attribut name vaut genre ET qui est actuellement coché ». Si aucun radio n'est coché, querySelector retourne null.
Testez ce code. Soumettez sans rien cocher, puis en cochant une option. Vérifiez les deux comportements.
3.3 Lire les cases à cocher (checkbox)
Contrairement aux radio, les checkbox permettent de cocher plusieurs options. On les lit avec .checked (qui retourne true ou false).
<h2>Centres d'intérêt</h2> <form id="formInterets"> <p><strong>Cochez vos centres d'intérêt :</strong></p> <div class="groupe-checkbox"> <input type="checkbox" id="sport" name="interet" value="Sport"> <label for="sport">Sport</label> <input type="checkbox" id="musique" name="interet" value="Musique"> <label for="musique">Musique</label> <input type="checkbox" id="lecture" name="interet" value="Lecture"> <label for="lecture">Lecture</label> <input type="checkbox" id="voyage" name="interet" value="Voyage"> <label for="voyage">Voyage</label> </div> <button type="submit">Valider</button> </form> <div id="resultatInterets" class="resultat" style="display:none;"></div>
let formInterets = document.querySelector("#formInterets"); let resultatInterets = document.querySelector("#resultatInterets"); function gererInterets(event) { event.preventDefault(); // querySelectorAll retourne TOUS les éléments correspondants let caseCochees = document.querySelectorAll('input[name="interet"]:checked'); if (caseCochees.length === 0) { resultatInterets.textContent = "Veuillez cocher au moins un intérêt."; resultatInterets.style.color = "red"; resultatInterets.style.display = "block"; return; } // Construire la liste des valeurs cochées let liste = []; for (let i = 0; i < caseCochees.length; i++) { liste.push(caseCochees[i].value); } resultatInterets.textContent = `Vos intérêts : ${liste.join(", ")}`; resultatInterets.style.color = "#333"; resultatInterets.style.display = "block"; } formInterets.addEventListener("submit", gererInterets);
querySelector vs querySelectorAll
querySelector()→ retourne le premier élément trouvé (ounull)querySelectorAll()→ retourne tous les éléments trouvés (une liste, même si vide)
Pour les checkbox, on utilise querySelectorAll car l'utilisateur peut cocher plusieurs cases.
Testez avec 0, 1, puis plusieurs cases cochées. Vérifiez que la liste s'affiche correctement avec des virgules.
3.4 Lire un select et un textarea
On les lit exactement comme un input texte, avec .value. Pas de surprise :
// Pour un <select id="pays"> let pays = document.querySelector("#pays").value; // → retourne la value de l'option sélectionnée // Pour un <textarea id="commentaire"> let commentaire = document.querySelector("#commentaire").value; // → retourne tout le texte saisi
Validation des Formulaires
4.1 Pourquoi valider ?
Analogie simple
Imaginez un guichet de poste. Avant de traiter votre courrier, l'agent vérifie : l'adresse est-elle complète ? Le timbre est-il collé ? Le poids est-il correct ? S'il manque quelque chose, il vous demande de corriger avant d'accepter le courrier.
La validation d'un formulaire, c'est exactement la même chose : on vérifie les données avant de les traiter ou de les envoyer.
Il existe deux niveaux de validation :
- Validation HTML (attributs) — simple, rapide, mais limitée
- Validation JavaScript — puissante, personnalisable, indispensable
4.2 Validation HTML avec les attributs
HTML fournit des attributs de validation natifs qui fonctionnent automatiquement dans un <form> :
| Attribut | Effet | Exemple |
|---|---|---|
required |
Champ obligatoire | <input required> |
minlength |
Longueur minimum | <input minlength="3"> |
maxlength |
Longueur maximum | <input maxlength="50"> |
min / max |
Valeur min/max (nombres) | <input type="number" min="0" max="20"> |
pattern |
Expression régulière | <input pattern="[0-9]{8}"> |
type="email" |
Vérifie le format email | <input type="email"> |
<!-- Exemples de validation HTML --> <input type="text" required minlength="2" maxlength="50"> <input type="email" required> <input type="number" min="0" max="20" required> <input type="tel" pattern="[0-9]{8}" title="8 chiffres attendus">
Limites de la validation HTML
La validation HTML affiche des messages par défaut du navigateur (en anglais selon les systèmes). Elle ne permet pas de personnaliser les messages, de comparer deux champs (ex : mot de passe et confirmation), ni de faire des vérifications complexes. C'est pour cela qu'on a besoin de JavaScript.
4.3 Validation JavaScript : les bonnes pratiques
Pour une validation professionnelle, on affiche un message d'erreur sous chaque champ qui pose problème, et on met en évidence le champ en erreur.
Créons un formulaire d'inscription complet :
index.html (à ajouter)<h2>Inscription</h2> <form id="formInscription"> <label for="inscNom">Nom complet :</label> <input type="text" id="inscNom"> <div class="erreur" id="erreurNom"></div> <label for="inscEmail">Email :</label> <input type="email" id="inscEmail"> <div class="erreur" id="erreurEmail"></div> <label for="inscMdp">Mot de passe :</label> <input type="password" id="inscMdp"> <div class="erreur" id="erreurMdp"></div> <label for="inscConfirm">Confirmer le mot de passe :</label> <input type="password" id="inscConfirm"> <div class="erreur" id="erreurConfirm"></div> <button type="submit">S'inscrire</button> </form> <div id="resultatInscription" class="resultat" style="display:none;"></div>
Remarquez la structure : chaque champ est suivi d'un <div class="erreur"> vide qui servira à afficher le message d'erreur correspondant.
let formInscription = document.querySelector("#formInscription"); // Fonction utilitaire : afficher une erreur sous un champ function afficherErreur(champId, erreurId, message) { document.querySelector(champId).classList.add("input-erreur"); document.querySelector(champId).classList.remove("input-valide"); document.querySelector(erreurId).textContent = message; } // Fonction utilitaire : marquer un champ comme valide function marquerValide(champId, erreurId) { document.querySelector(champId).classList.remove("input-erreur"); document.querySelector(champId).classList.add("input-valide"); document.querySelector(erreurId).textContent = ""; } function validerInscription(event) { event.preventDefault(); let nom = document.querySelector("#inscNom").value.trim(); let email = document.querySelector("#inscEmail").value.trim(); let mdp = document.querySelector("#inscMdp").value; let confirm = document.querySelector("#inscConfirm").value; let estValide = true; // Validation du nom if (nom === "") { afficherErreur("#inscNom", "#erreurNom", "Le nom est obligatoire."); estValide = false; } else if (nom.length < 2) { afficherErreur("#inscNom", "#erreurNom", "Le nom doit contenir au moins 2 caractères."); estValide = false; } else { marquerValide("#inscNom", "#erreurNom"); } // Validation de l'email if (email === "") { afficherErreur("#inscEmail", "#erreurEmail", "L'email est obligatoire."); estValide = false; } else if (!email.includes("@") || !email.includes(".")) { afficherErreur("#inscEmail", "#erreurEmail", "Format email invalide."); estValide = false; } else { marquerValide("#inscEmail", "#erreurEmail"); } // Validation du mot de passe if (mdp === "") { afficherErreur("#inscMdp", "#erreurMdp", "Le mot de passe est obligatoire."); estValide = false; } else if (mdp.length < 6) { afficherErreur("#inscMdp", "#erreurMdp", "Minimum 6 caractères."); estValide = false; } else { marquerValide("#inscMdp", "#erreurMdp"); } // Validation de la confirmation if (confirm === "") { afficherErreur("#inscConfirm", "#erreurConfirm", "Veuillez confirmer le mot de passe."); estValide = false; } else if (confirm !== mdp) { afficherErreur("#inscConfirm", "#erreurConfirm", "Les mots de passe ne correspondent pas."); estValide = false; } else { marquerValide("#inscConfirm", "#erreurConfirm"); } // Si tout est valide if (estValide) { let res = document.querySelector("#resultatInscription"); res.style.display = "block"; res.textContent = `Inscription réussie pour ${nom} (${email}).`; res.style.color = "green"; formInscription.reset(); // Vider tous les champs du formulaire } } formInscription.addEventListener("submit", validerInscription);
Décryptage du code
Voici les points clés à retenir :
.trim()— supprime les espaces au début et à la fin (évite qu'un champ rempli d'espaces passe la validation)classList.add()/classList.remove()— ajoute ou retire une classe CSS (pour changer l'apparence du champ)- Le drapeau
estValide— commence àtrue. Chaque erreur le passe àfalse. On ne soumet que si toutes les vérifications passent formInscription.reset()— remet tous les champs du formulaire à leur valeur initiale
Testez le formulaire d'inscription. Essayez : tous les champs vides, un email sans @, un mot de passe trop court, deux mots de passe différents, puis une inscription valide. Observez les bordures rouges/vertes et les messages.
Les Événements focus et blur
5.1 C'est quoi focus et blur ?
Analogie simple
Quand vous cliquez dans un champ texte, le curseur apparaît et le champ est prêt à recevoir votre saisie — c'est le focus (le projecteur est braqué sur ce champ).
Quand vous cliquez ailleurs ou appuyez sur Tab, le champ perd le focus — c'est le blur (le projecteur se déplace).
| Événement | Se déclenche quand... | Usage courant |
|---|---|---|
"focus" |
L'utilisateur entre dans un champ | Afficher une aide, un indice |
"blur" |
L'utilisateur quitte un champ | Valider le champ immédiatement |
5.2 Validation au blur (champ par champ)
Au lieu d'attendre que l'utilisateur clique sur « Envoyer », on peut valider chaque champ dès qu'il le quitte. C'est une meilleure expérience utilisateur.
index.html (à ajouter)<h2>Validation au blur</h2> <form id="formBlur"> <label for="blurNom">Nom :</label> <input type="text" id="blurNom"> <div class="erreur" id="errBlurNom"></div> <label for="blurAge">Âge :</label> <input type="number" id="blurAge"> <div class="erreur" id="errBlurAge"></div> <button type="submit">Envoyer</button> </form>
// Validation du nom quand l'utilisateur quitte le champ let blurNom = document.querySelector("#blurNom"); blurNom.addEventListener("blur", function() { let valeur = blurNom.value.trim(); if (valeur === "") { afficherErreur("#blurNom", "#errBlurNom", "Le nom est obligatoire."); } else { marquerValide("#blurNom", "#errBlurNom"); } }); // Validation de l'âge quand l'utilisateur quitte le champ let blurAge = document.querySelector("#blurAge"); blurAge.addEventListener("blur", function() { let age = Number(blurAge.value); if (blurAge.value === "") { afficherErreur("#blurAge", "#errBlurAge", "L'âge est obligatoire."); } else if (age < 1 || age > 120) { afficherErreur("#blurAge", "#errBlurAge", "L'âge doit être entre 1 et 120."); } else { marquerValide("#blurAge", "#errBlurAge"); } }); // Soumission du formulaire document.querySelector("#formBlur").addEventListener("submit", function(event) { event.preventDefault(); // Déclencher le blur sur tous les champs pour forcer la validation blurNom.dispatchEvent(new Event("blur")); blurAge.dispatchEvent(new Event("blur")); // Vérifier s'il reste des erreurs let erreurs = document.querySelectorAll("#formBlur .input-erreur"); if (erreurs.length === 0) { alert("Formulaire valide !"); } });
Résultat
L'erreur apparaît dès que l'utilisateur quitte un champ, sans attendre la soumission. C'est plus réactif et plus agréable. Lors de la soumission, on re-déclenche le blur pour attraper les champs jamais visités.
Testez en cliquant dans le champ Nom, puis cliquez ailleurs sans rien écrire. L'erreur doit apparaître immédiatement. Faites de même avec le champ Âge.
Formulaires Dynamiques
6.1 Activer/désactiver un champ
On peut rendre un champ inaccessible avec la propriété disabled. C'est utile quand un champ ne doit être rempli que si une condition est remplie.
<h2>Champs conditionnels</h2> <form id="formConditionnel"> <div class="groupe-checkbox"> <input type="checkbox" id="aEntreprise"> <label for="aEntreprise">Je travaille dans une entreprise</label> </div> <label for="nomEntreprise">Nom de l'entreprise :</label> <input type="text" id="nomEntreprise" disabled placeholder="Cochez la case ci-dessus"> </form>
let caseEntreprise = document.querySelector("#aEntreprise"); let champEntreprise = document.querySelector("#nomEntreprise"); caseEntreprise.addEventListener("change", function() { if (caseEntreprise.checked) { // Activer le champ champEntreprise.disabled = false; champEntreprise.placeholder = "Nom de votre entreprise"; champEntreprise.focus(); // Placer le curseur dans le champ } else { // Désactiver et vider le champ champEntreprise.disabled = true; champEntreprise.value = ""; champEntreprise.placeholder = "Cochez la case ci-dessus"; } });
Propriétés utiles
element.disabled = true/false— active ou désactive un champelement.focus()— place le curseur dans un champ (pratique pour guider l'utilisateur)element.placeholder = "..."— modifie le texte indicatif
Testez le code. Cochez et décochez la case. Le champ entreprise doit s'activer/se désactiver dynamiquement.
6.2 Afficher/masquer une section selon un choix
Un cas très courant : afficher des champs supplémentaires selon la valeur choisie dans une liste déroulante.
index.html (à ajouter)<h2>Mode de paiement</h2> <form id="formPaiement"> <label for="modePaiement">Paiement par :</label> <select id="modePaiement"> <option value="">-- Choisir --</option> <option value="carte">Carte bancaire</option> <option value="virement">Virement bancaire</option> </select> <div id="sectionCarte" style="display:none;"> <label for="numCarte">Numéro de carte :</label> <input type="text" id="numCarte" placeholder="1234 5678 9012 3456"> </div> <div id="sectionVirement" style="display:none;"> <label for="iban">IBAN :</label> <input type="text" id="iban" placeholder="TN59 1234 5678 9012 3456 78"> </div> </form>
let modePaiement = document.querySelector("#modePaiement"); let sectionCarte = document.querySelector("#sectionCarte"); let sectionVirement = document.querySelector("#sectionVirement"); modePaiement.addEventListener("change", function() { let choix = modePaiement.value; // Masquer toutes les sections d'abord sectionCarte.style.display = "none"; sectionVirement.style.display = "none"; // Afficher la section correspondante if (choix === "carte") { sectionCarte.style.display = "block"; } else if (choix === "virement") { sectionVirement.style.display = "block"; } });
Résultat
Quand l'utilisateur choisit « Carte bancaire », le champ numéro de carte apparaît. Quand il choisit « Virement », le champ IBAN apparaît. Quand il revient à « -- Choisir -- », tout disparaît.
Testez en changeant le mode de paiement. Vérifiez que les sections s'affichent et se masquent correctement.
6.3 Réinitialiser un formulaire
Deux méthodes pour remettre un formulaire à zéro :
// Méthode 1 : Le bouton HTML reset (automatique) // <button type="reset">Réinitialiser</button> // Méthode 2 : En JavaScript document.querySelector("#monFormulaire").reset(); // → Remet TOUS les champs du formulaire à leur valeur par défaut
Quand utiliser reset() ?
Après une soumission réussie, appelez form.reset() pour vider les champs. N'oubliez pas d'effacer aussi les messages d'erreur et les classes CSS input-erreur / input-valide manuellement, car reset() ne touche pas aux classes ni au contenu des <div>.
Le Schéma à Retenir
Tout formulaire interactif en JavaScript suit ce schéma en 4 étapes :
// ======================================== // ÉTAPE 1 : SÉLECTIONNER le formulaire // ======================================== let form = document.querySelector("#monFormulaire"); // ======================================== // ÉTAPE 2 : ÉCRIRE la validation // ======================================== function valider(event) { event.preventDefault(); // Empêcher le rechargement // a) Lire les valeurs : .value, .checked // b) Vérifier chaque champ // c) Afficher les erreurs ou le succès } // ======================================== // ÉTAPE 3 : ASSOCIER l'événement "submit" // ======================================== form.addEventListener("submit", valider); // ======================================== // ÉTAPE 4 (bonus) : VALIDER en temps réel // ======================================== // Ajouter des écouteurs "blur" ou "input" // sur les champs individuels
Résumé en une phrase
« J'intercepte la soumission, je lis les valeurs, je vérifie tout, et j'affiche le résultat ou les erreurs. »
Exercices
Pour chaque exercice, créez le HTML et le JavaScript nécessaires. Suivez le schéma en 4 étapes et réutilisez les fonctions afficherErreur et marquerValide.
Exercice 1 Formulaire de réservation
Créez un formulaire de réservation de restaurant avec :
- Nom (texte, obligatoire, min 2 caractères)
- Date de réservation (date, obligatoire, ne doit pas être dans le passé)
- Nombre de personnes (nombre, obligatoire, entre 1 et 20)
- Un
<select>pour l'heure (12h, 13h, 19h, 20h, 21h) - Un
<textarea>pour les remarques (optionnel)
Validez tous les champs à la soumission. Affichez un résumé de la réservation si tout est correct.
Indice pour la date : comparez avec new Date().toISOString().split("T")[0] qui donne la date du jour au format "2026-03-31".
Exercice 2 Formulaire de commande de pizza
Créez un formulaire de commande avec :
- Nom du client (texte, obligatoire)
- Taille de la pizza : radio (Petite = 8 DT, Moyenne = 12 DT, Grande = 16 DT)
- Suppléments : checkbox (Fromage +2 DT, Champignons +1.5 DT, Olives +1 DT, Viande +3 DT)
- Un bouton « Commander »
À la soumission, affichez un récapitulatif avec le nom, la taille choisie, les suppléments, et le prix total.
Indice : associez les prix aux value de vos <input> et utilisez Number() pour les additionner.
Exercice 3 Validation en temps réel complète
Créez un formulaire d'inscription avec validation au blur sur chaque champ :
- Nom (min 2 caractères)
- Email (doit contenir
@et.) - Téléphone (exactement 8 chiffres — utilisez
.length) - Mot de passe (min 8 caractères, doit contenir au moins un chiffre)
- Confirmation du mot de passe (doit être identique)
Chaque champ se valide dès qu'on le quitte (blur). La soumission ne passe que si tous les champs sont valides.
Indice pour le chiffre dans le mot de passe : parcourez chaque caractère avec une boucle for et utilisez !isNaN(caractere) pour tester si c'est un chiffre.
Exercice 4 Formulaire conditionnel (sondage)
Créez un sondage qui s'adapte selon les réponses :
- Question 1 : « Êtes-vous étudiant ? » (radio : Oui / Non)
- Si Oui → afficher un champ « Établissement » et un
<select>« Niveau d'études » (Licence 1, Licence 2, Licence 3, Master 1, Master 2) - Si Non → afficher un champ « Profession » et un champ « Entreprise »
- Question 2 : « Acceptez-vous les conditions d'utilisation ? » (checkbox, obligatoire)
- Un bouton « Envoyer » désactivé tant que les conditions ne sont pas acceptées
Indice pour le bouton : écoutez "change" sur la checkbox et modifiez bouton.disabled.
Exercice 5 Formulaire multi-étapes
Créez un formulaire en 3 étapes qui affiche une section à la fois :
- Étape 1 : Informations personnelles (Nom, Email) + bouton « Suivant »
- Étape 2 : Adresse (Ville, Code postal, Pays via
<select>) + boutons « Précédent » et « Suivant » - Étape 3 : Récapitulatif de toutes les données + bouton « Confirmer »
Chaque étape est un <div> qu'on affiche ou masque. Validez les champs avant de passer à l'étape suivante. À l'étape 3, affichez un résumé de tout ce qui a été saisi.
Indices :
- Utilisez
style.display = "none"/"block"pour montrer/cacher les étapes - Les boutons « Suivant » et « Précédent » doivent être de type
"button"(pas"submit") - Seul le bouton « Confirmer » à l'étape 3 sera de type
"submit"
Récapitulatif
| Concept | Syntaxe |
|---|---|
| Intercepter la soumission | form.addEventListener("submit", fn) |
| Empêcher le rechargement | event.preventDefault() |
| Lire un champ texte/email/password | input.value |
| Lire un checkbox / radio | input.checked → true / false |
| Lire le radio coché d'un groupe | querySelector('input[name="x"]:checked') |
| Lire toutes les checkbox cochées | querySelectorAll('input[name="x"]:checked') |
| Lire un select | select.value |
| Lire un textarea | textarea.value |
| Supprimer les espaces inutiles | chaine.trim() |
| Ajouter / retirer une classe CSS | el.classList.add("x") / .remove("x") |
| Activer / désactiver un champ | input.disabled = true / false |
| Donner le focus à un champ | input.focus() |
| Réinitialiser un formulaire | form.reset() |
| Validation au départ du champ | input.addEventListener("blur", fn) |
| Afficher / masquer un élément | el.style.display = "block" / "none" |