Module 4Gérer les événements utilisateur
Chapitre 12 sur 15
Gérer les éléments d'un formulaire
Lire les champs, intercepter l'envoi d'un formulaire et le valider côté client.
- ≈ 120 min
- 4 leçons
- 1 vidéo
- 3 exercices
Module 4Gérer les événements utilisateur
Chapitre 12 sur 15
Lire les champs, intercepter l'envoi d'un formulaire et le valider côté client.
Objectifs
Avec ce chapitre, tu sauras…
input, change et submit ;preventDefault() ;Leçon 1
| Champ | Propriété à lire | Exemple |
|---|---|---|
texte, email, nombre, textarea | value (toujours une chaîne) | champ.value |
| nombre (en nombre) | valueAsNumber ou Number(champ.value) | age.valueAsNumber |
| case à cocher | checked (true / false) | conditions.checked |
| boutons radio | la valeur du bouton coché | form.querySelector('input[name="genre"]:checked')?.value |
liste select | value (l'option choisie) | ville.value |
| Événement | Se déclenche… | Usage |
|---|---|---|
input | à chaque modification (chaque caractère tapé) | compteur de caractères, recherche en direct, vérification instantanée |
change | quand la valeur est validée (champ quitté, case cochée, option choisie) | select, cases à cocher, boutons radio |
focus / blur | quand le champ reçoit / perd le curseur | afficher une aide, vérifier en quittant le champ |
submit | sur le formulaire, à l'envoi (bouton submit ou touche Entrée) | validation avant envoi |
Vidéo · À regarder
ENJavaScript Full Course for free
Bro Code · YouTube
Leçon 2
| Méthode | Effet |
|---|---|
form.submit() | envoie le formulaire à l'adresse de l'attribut action (sans déclencher l'événement submit, donc sans validation) |
form.requestSubmit() | envoie le formulaire comme un clic sur le bouton d'envoi : la validation et l'événement submit ont lieu |
form.reset() | réinitialise tous les champs à leur valeur initiale |
Leçon 3
Leçon 4
| Attribut | Contrainte |
|---|---|
required | champ obligatoire |
type="email", type="url", type="number", type="date" | format du type |
min, max, step | valeur minimale, maximale, pas (nombres, dates) |
minlength, maxlength | longueur minimale, maximale du texte |
1La valeur d'un <input type="number"> lue avec .value est…
2Pour savoir si une case est cochée :
3L'événement déclenché à chaque caractère tapé est…
4Pour empêcher l'envoi d'un formulaire :
5form.reset()…
6La validation côté serveur est…
7L'attribut qui impose une expression régulière est…
L'essentiel du chapitre
value (toujours une chaîne), checked (cases, radios), select.value ; new FormData(form).input (chaque frappe), change (valeur validée), focus / blur, submit sur le formulaire.form.submit() envoie sans validation ; form.requestSubmit() avec ; form.reset() réinitialise.e.preventDefault() dans submit : bloque l'envoi pour valider ou envoyer en AJAX.required, type, min, max, minlength, pattern ; CSS : :valid, :invalid, :user-invalid.reset| sur le formulaire, à la réinitialisation |
pattern="regex" |
| la saisie doit correspondre à l'expression régulière |
disabled | champ désactivé (non envoyé) |
| Pseudo-classe | Sélectionne les champs… |
|---|---|
:required / :optional | obligatoires / facultatifs |
:valid / :invalid | dont la valeur est valide / invalide |
:disabled | désactivés |
:user-invalid | invalides après que l'utilisateur les a modifiés (évite d'afficher des erreurs dès le chargement) |
<form id="inscription" action="/inscription.php" method="post">
<label>Nom <input type="text" name="nom" id="nom"></label>
<label>E-mail <input type="email" name="email" id="email"></label>
<label>Âge <input type="number" name="age" id="age"></label>
<label>Filière
<select name="filiere" id="filiere">
<option value="">-- Choisir --</option>
<option value="dev">Développement digital</option>
<option value="infra">Infrastructure digitale</option>
</select>
</label>
<label><input type="radio" name="cours" value="jour"> Cours du jour</label>
<label><input type="radio" name="cours" value="soir"> Cours du soir</label>
<label><input type="checkbox" id="conditions"> J'accepte le règlement</label>
<button type="submit">S'inscrire</button>
<button type="reset">Effacer</button>
</form>
<p id="message"></p>const form = document.querySelector("#inscription");
const nom = form.querySelector("#nom").value.trim();
const age = Number(form.querySelector("#age").value);
const filiere = form.querySelector("#filiere").value;
const cours = form.querySelector('input[name="cours"]:checked')?.value; // undefined si aucun
const accepte = form.querySelector("#conditions").checked;
// accès par le nom : document.forms["inscription"]["nom"].value
// ou tout d'un coup avec FormData :
const donnees = Object.fromEntries(new FormData(form)); // { nom: "...", email: "...", ... }Tableau: Les événements des champs
const bio = document.querySelector("#bio"); // <textarea id="bio" maxlength="200">
const reste = document.querySelector("#reste");
bio.addEventListener("input", () => {
reste.textContent = `${200 - bio.value.length} caractères restants`;
});La propriété checked des cases à cocher et des boutons radio (en anglais).
<form id="FORM1" method="post" action="/code.php">
<label>Nom <input type="text" name="nom"></label>
<label>Âge <input type="text" name="age"></label>
<input type="button" id="btnEnvoyer" value="ENVOYER">
<input type="button" id="btnEffacer" value="EFFACER">
</form>
<p id="message"></p>
<script>
const form = document.getElementById("FORM1");
document.getElementById("btnEnvoyer").addEventListener("click", () => form.submit());
document.getElementById("btnEffacer").addEventListener("click", () => {
form.reset();
document.getElementById("message").textContent = "Formulaire réinitialisé";
});
</script>Dans l'exemple du résumé, le bouton appelle SoumettreForm() alors que la fonction s'appelle SubmitForm() : le clic provoque une ReferenceError. De plus, ce bouton est de type submit : il envoie déjà le formulaire tout seul, l'appel à submit() est donc inutile. On utilise form.submit() avec un bouton de type button, comme ci-dessus.
event.preventDefault() annule l'action par défaut de l'événement. Pour l'événement submit, l'action par défaut est l'envoi du formulaire et le rechargement de la page : on l'annule pour valider les données d'abord, ou pour les envoyer en AJAX (chapitre 14) sans recharger la page.
const form = document.querySelector("#inscription");
form.addEventListener("submit", (e) => {
e.preventDefault(); // le formulaire n'est pas envoyé
console.log("Données :", Object.fromEntries(new FormData(form)));
});L'événement submit se déclenche quelle que soit la façon d'envoyer : clic sur le bouton ou touche Entrée dans un champ. Un écouteur click sur le bouton ne capte pas la touche Entrée.
La validation vérifie que les saisies sont conformes à ce qui est attendu : les champs obligatoires sont remplis, une date est valide, un numéro ne contient que des chiffres… Elle se fait à deux endroits :
Tableau: La validation par les attributs HTML5
Reprends le formulaire d'inscription de la section 1. À l'envoi, valide tous les champs (nom d'au moins 2 lettres, e-mail valide, âge entre 15 et 35, filière choisie, type de cours choisi, règlement accepté). En cas d'erreurs, affiche-les sous chaque champ. Si tout est valide, cache le formulaire et affiche un récapitulatif : « Merci Sara, ton inscription en Développement digital (cours du soir) est enregistrée. »
Crée un champ mot de passe et un champ de confirmation. À chaque saisie (input), affiche sous le premier champ la liste des règles, chacune en vert si elle est respectée et en rouge sinon : au moins 8 caractères, une majuscule, un chiffre, un caractère spécial. Le bouton d'envoi reste désactivé (disabled) tant que toutes les règles ne sont pas respectées et que les deux mots de passe ne sont pas identiques.
Un formulaire de commande contient une liste select de formations (HTML 800 DH, JavaScript 1200 DH, React 1500 DH), un champ nombre « Nombre de participants » (de 1 à 20) et une case « Paiement en une fois (−10 %) ». Le total s'affiche et se met à jour automatiquement à chaque changement, sans bouton.
<form action="/code.php" method="post">
<input type="text" name="nom" required minlength="2">
<input type="email" name="email" required>
<input type="tel" name="tel" pattern="0[5-7][0-9]{8}" title="10 chiffres, commençant par 05, 06 ou 07">
<input type="number" name="age" min="15" max="35">
<input type="submit" value="Envoyer">
</form>Tableau: La validation par les sélecteurs CSS
input:user-invalid { border: 2px solid #c0392b; }
input:valid { border: 2px solid #27ae60; }La validation en JavaScript
form.addEventListener("submit", (e) => {
const nom = form.querySelector("#nom").value.trim();
if (nom === "") {
e.preventDefault();
alert("Le champ « nom » doit être saisi");
}
});submit et appeler e.preventDefault().erreur).form.submit(), ou une requête AJAX.const form = document.querySelector("#inscription");
function erreur(champ, message) {
champ.classList.add("erreur");
const p = document.createElement("p");
p.className = "msg-erreur";
p.textContent = message;
champ.closest("label").after(p);
}
form.addEventListener("submit", (e) => {
e.preventDefault();
form.querySelectorAll(".msg-erreur").forEach(p => p.remove()); // 2. effacer
form.querySelectorAll(".erreur").forEach(c => c.classList.remove("erreur"));
let valide = true;
const nom = form.querySelector("#nom");
const email = form.querySelector("#email");
const age = form.querySelector("#age");
if (nom.value.trim().length < 2) {
erreur(nom, "Le nom doit contenir au moins 2 caractères.");
valide = false;
}
if (!/^[\w.-]+@[\w-]+\.[a-z]{2,}$/i.test(email.value)) {
erreur(email, "L'adresse e-mail n'est pas valide.");
valide = false;
}
const n = Number(age.value);
if (!Number.isInteger(n) || n < 15 || n > 35) {
erreur(age, "L'âge doit être un entier entre 15 et 35.");
valide = false;
}
if (!form.querySelector("#conditions").checked) {
alert("Tu dois accepter le règlement.");
valide = false;
}
if (valide) {
document.querySelector("#message").textContent = "Inscription envoyée !";
// form.submit(); ou un envoi AJAX (chapitre 14)
}
});Le DOM donne aussi accès aux contraintes HTML5 : champ.checkValidity() renvoie true si le champ respecte ses attributs, champ.validity.valueMissing indique un champ obligatoire vide, champ.setCustomValidity("message") définit un message d'erreur personnalisé, et l'attribut novalidate sur le <form> désactive les bulles du navigateur pour afficher ses propres messages.
L'exemple d'interruption du résumé appelle window.history.back() après preventDefault() : l'utilisateur est renvoyé à la page précédente quand il clique sur « Envoyer ». Ce n'est qu'une démonstration de history.back() ; dans un vrai formulaire, on affiche plutôt les erreurs ou un message de confirmation.