Skip to content

Module 10 : JavaScript - Formulaires et validation

Introduction

Les formulaires sont au cœur de l'interaction utilisateur dans les applications web. Ce module explore comment JavaScript permet de gérer les événements de formulaire, valider les données saisies, et manipuler dynamiquement les éléments du DOM pour créer des expériences utilisateur riches et interactives.

Objectifs du cours

  • Comprendre et utiliser les événements de formulaire en JavaScript
  • Maîtriser les méthodes preventDefault() et submit() pour contrôler la soumission de formulaires
  • Utiliser l'objet event et sa propriété target pour accéder aux éléments déclencheurs
  • Implémenter des techniques de validation de formulaires en JavaScript, y compris la validation en temps réel
  • Accéder et manipuler les éléments du DOM avec getElementById, getAttribute et setAttribute
  • Manipuler le contenu des éléments HTML avec textContent, value et innerHTML

Théorie

1 : Accéder aux éléments du DOM en JavaScript

Définition

Accéder aux éléments du DOM permet de manipuler dynamiquement le contenu et les attributs des éléments HTML via JavaScript.

Contexte d'utilisation

Ces méthodes sont essentielles pour interagir avec les éléments de la page, notamment dans les formulaires.

getElementById(ID)

La méthode getElementById(ID) permet de récupérer une référence à un élément HTML à partir de son ID. Elle renvoie un seul objet.

html
<div id="mon-element">Ceci est un élément avec un ID.</div>
javascript
// Récupérer une référence à l'élément avec l'ID "mon-element"
let monElement = document.getElementById("mon-element");

getAttribute

La méthode getAttribute permet d'obtenir la valeur d'un attribut spécifié pour un élément HTML.

javascript
// Obtient l'élément de paragraphe par son ID
let paragraphe = document.getElementById("monParagraphe");

// Obtient la valeur de l'attribut "class" du paragraphe
let classe = paragraphe.getAttribute("class");

// Affiche la valeur dans la console
console.log("La classe du paragraphe est : " + classe);

setAttribute

La méthode setAttribute permet de définir la valeur d'un attribut spécifié pour un élément HTML.

javascript
// Définit la classe du paragraphe
paragraphe.setAttribute("class", "msg-erreur");

Démo : Modifier la classe d'une div au clic sur un bouton

Voici un exemple simple où un bouton permet de changer la classe CSS d'une div lorsqu'on clique dessus :

html
<div id="maDiv" class="rouge">Je change de couleur !</div>
<button id="btnChangerClasse">Changer la classe</button>
css
.rouge {
    background-color: red;
    color: white;
}
.vert {
    background-color: green;
    color: white;
}
javascript

function gererClick() {
    let div = document.getElementById("maDiv");

    let classe = div.getAttribute("class");
    // On alterne la classe entre 'rouge' et 'vert'
    if (classe === "rouge") {
        div.setAttribute("class", "vert");
    } else {
        div.setAttribute("class", "rouge");
    }
}

function initialisation() {
    let btn = document.getElementById("btnChangerClasse");
    btn.addEventListener("click", gererClick, false);
}

addEventListener("load", initialisation);

Explication du code :

  • Nous avons une div avec l'ID "maDiv" qui a initialement la classe "rouge".
  • Nous avons un bouton avec l'ID "btnChangerClasse". Lorsque ce bouton est cliqué, nous récupérons la div et vérifions sa classe actuelle. Si la classe est "rouge", nous la changeons en "vert". Sinon, nous la changeons en "rouge". Ainsi, à chaque clic sur le bouton, la couleur de fond de la div bascule entre rouge et vert.

2 : Manipuler le contenu

Définition

Manipuler le contenu des éléments HTML permet de changer dynamiquement le texte ou le HTML affiché. Essentiellement, il y a 2 bonnes façons de manipuler le contenu d'un élément HTML : textContent et value.

textContent

textContent ne renvoie que le texte brut de l'élément HTML, sans balises.

html
<p id="p1">Allo je suis un paragraphe</p>
javascript
// Accéder au contenu texte d'une balise HTML
let text = document.getElementById("p1").textContent;

value

La propriété value est utilisée pour les éléments de formulaire comme input, textarea, select. Elle représente la valeur actuelle dans le champ de formulaire.

html
<input id="nom" name="nom" type="text">
javascript
// Récupérer/Changer le contenu d'une balise de formulaire
let text = document.getElementById("nom").value;

innerHTML

La propriété innerHTML permet de récupérer ou modifier le contenu HTML d'un élément, incluant les balises.

Attention : Méthode à éviter pour créer des balises HTML ; utiliser createElement() à la place.

html
<div id="monElement">Je suis un élément avec un ID</div>
javascript
let uneDiv = document.getElementById("monElement");
uneDiv.innerHTML = '<h2>Allo</h2>';

3 : CurrentTarget et event

Définition

Le mot-clé "currentTarget" est utilisé dans le contexte des événements pour représenter l'élément HTML sur lequel un événement a été déclenché. L'objet "event" contient des informations sur l'événement, et currentTarget est l'élément déclencheur.

Contexte d'utilisation

Lorsqu'un événement se produit, currentTarget permet d'accéder aux propriétés de l'élément qui a déclenché l'événement, comme son ID, sa classe, son tagName, etc.

Exemples pratiques

Liste des propriétés des objets HTML utilisables avec currentTarget : https://www.w3schools.com/jsref/dom_obj_all.asp

html
<button id="myButton" class="btn">Cliquez ici</button>
javascript
function gererClick(event) {
  console.log("Le bouton a été cliqué !");
  console.log("Voici son ID :", event.currentTarget.id); // Affiche myButton
  console.log("Voici sa class :", event.currentTarget.className); // Affiche btn
  console.log("Voici son tagName :", event.currentTarget.tagName); // Affiche BUTTON
  console.log("Voici son contenu :", event.currentTarget.textContent); // Affiche "Cliquez ici"
  // [...] Vous pouvez ajouter d'autres propriétés selon vos besoins
}

function initialisation() {
    let btn = document.getElementById("myButton");
    btn.addEventListener("click", gererClick, false);
}

addEventListener("load", initialisation);

Explication du code

Dans cet exemple, nous avons un bouton avec l'ID "myButton". Nous attachons un gestionnaire d'événements pour le clic sur ce bouton. Lorsque le bouton est cliqué, la fonction gererClick est appelée, et elle utilise event.currentTarget pour accéder aux propriétés de l'élément qui a déclenché l'événement (le bouton). Nous affichons différentes propriétés du bouton dans la console.

Avantage principal de currentTarget : permet d'optenir des informations sur l'élément qui a déclenché l'événement sans avoir à nécessairement faire un getElementById() ou une autre méthode de sélection d'élément, ce qui rend le code plus flexible dynamique, surtout dans des situations où le même gestionnaire d'événements est attaché à plusieurs éléments.

Autre exemple

Optenir le contenu d'une div cliquée :

html
<div id="div1">Contenu de la div 1</div>
<div id="div2">Contenu de la div 2</div>
javascript
function gererClick(event) {
  console.log("Une div a été cliquée !");
  console.log("Voici son ID :", event.currentTarget.id);
  console.log("Voici son contenu :", event.currentTarget.textContent);
}

function initialisation() {
  let div1 = document.getElementById("div1");
  let div2 = document.getElementById("div2");
  div1.addEventListener("click", gererClick, false);
  div2.addEventListener("click", gererClick, false);
}

addEventListener("load", initialisation);

Exercice pratique

Voir exercice 1

4 : Événements du formulaire

Définition

Les événements du formulaire en JavaScript sont des événements qui se produisent lorsqu'un utilisateur interagit avec des éléments de formulaire, tels que les champs de saisie de texte, les boutons de formulaire, les cases à cocher, les boutons radio, les listes déroulantes, etc.

Contexte d'utilisation

Ces événements permettent de détecter les actions de l'utilisateur sur les éléments de formulaire et de déclencher des fonctions en réponse, rendant les formulaires interactifs et permettant une validation en temps réel.

Exemples pratiques

Voici une liste des principaux événements du formulaire :

  • reset : déclenché lorsqu'un formulaire est réinitialisé.
  • change : déclenché lorsqu'une valeur de champ de formulaire est modifiée et après que l'utilisateur soit sorti du champ.
  • input : déclenché dès que la valeur d'un champ de formulaire est modifiée.
  • focus : déclenché lorsqu'un champ de formulaire reçoit le focus.
  • blur : déclenché lorsqu'un champ de formulaire perd le focus.
  • keydown : déclenché lorsqu'un utilisateur appuie sur une touche du clavier alors qu'il se trouve dans un champ de formulaire.

Événement spécial : submit()

  • submit : déclenché lorsqu'un formulaire est soumis. Cet événement est particulièrement important car il permet de contrôler la soumission du formulaire, notamment en utilisant preventDefault() pour empêcher le comportement par défaut de rechargement de la page.

Soit le formulaire suivant :

html
<form id="mon-formulaire" novalidate>
  <label for="nom">Nom :</label>
  <input type="text" id="nom" name="nom"><br>

  <label for="email">Email :</label>
  <input type="email" id="email" name="email"><br>

  <button type="submit">Envoyer</button>
</form>

Normalement, lorsque l'utilisateur clique sur le bouton "Envoyer", le formulaire est soumis et la page est rechargée. Résultat : toutes les données saisies sont perdues, et le JavaScript en cours d'exécution est interrompu. Cependant, en utilisant JavaScript, nous pouvons intercepter cet événement de soumission pour effectuer des actions personnalisées, comme valider les données avant de les envoyer au serveur.

Exemple pour gérer le submit :

javascript

function validerNom() {
    // Logique de validation du champ nom
    // Par exemple, vérifier que le champ n'est pas vide
    let nomInput = document.getElementById("nom");
    if (nomInput.value === '') {
        // Afficher un message d'erreur et mettre en surbrillance le champ en erreur
        alert("Le champ nom ne peut pas être vide.");
        return false; // Champ invalide
    } else {
        return true; // Champ valide
    }
}

function gererSubmit(event) {
   // Empêche la soumission du formulaire (bloque la soumission)   
   event.preventDefault(); 

   if(validerNom()) {
       // Si on décide d'envoyer le formulaire, ce serait event.target.submit(); pour soumettre le formulaire au serveur (ce que l'on veut éviter pour le moment, car on veut juste valider le formulaire sans le soumettre à un serveur)
       // Maintenant, on peut effectuer une validation personnalisée des données soumises et ensuite décider si on envoi le formulaire ou encore si on fait autre chose en javascript
   }
}

function initialisation() {
    
    // D'abord, on récupère une référence au formulaire
    let form = document.getElementById('mon-formulaire');
    // Ensuite, on attrape la soumission du formulaire par l'événement submit afin de pouvoir le contrôler et éviter que la page soit automatiquement rechargée
    form.addEventListener('submit', gererSubmit);

    // Ensuite, on peut aussi attraper d'autres événements sur les champs du formulaire pour faire de la validation en temps réel, par exemple :
    let nom = document.getElementById("nom");
    
    // Exemple 1 : Lorsque l'utilisateur MODIFIE quoi que ce soit dans le champ
    nom.addEventListener("input", validerNom);

    // Exemple 2 : Lorsque l'utilisateur SORT du champ
    // nom.addEventListener("blur", validerNom);

    // Exemple 3 : Lorsque l'utilisateur APPUIE sur une touche du clavier dans le champ
    // nom.addEventListener("keydown", validerNom);

}

addEventListener("load", initialisation);

5 : Fonctions preventDefault() et submit()

Contexte d'utilisation

Lorsqu'un formulaire est soumis, le comportement par défaut du navigateur est de recharger la page. Si une page est rechargée, toutes les données saisies sont perdues, incluant le javascript en cours d'exécution. La méthode preventDefault() est utilisée pour empêcher ce comportement par défaut, permettant ainsi de gérer la soumission du formulaire de manière personnalisée, comme effectuer une validation avant de soumettre les données.

preventDefault()

La fonction preventDefault() est utilisée pour empêcher le comportement par défaut d'un événement.

submit()

La méthode submit() permet de soumettre programmatiquement un formulaire.

Exemples pratiques

Voici un exemple de code qui empêche la soumission d'un formulaire et affiche une alerte si les champs sont invalides. Si les champs sont valides, on utilise submit() pour soumettre le formulaire :

html
<form id="formulaire">
  <label for="nom">Nom :</label>
  <input type="text" id="nom" name="nom" required>
  <!-- autres champs -->
  <button type="submit">Envoyer</button>
</form>
javascript
function gererSubmit(event) {
  event.preventDefault(); // Empêche la soumission du formulaire (bloque la soumission, pour le moment)
   
  // Effectue une validation personnalisée des données soumises
  if (validationCondition) {
     // Si les champs sont valides, le formulaire peut être envoyé. On utilise la méthode submit() pour soumettre le formulaire.
     event.target.submit();
  } else {
     // Sinon, on affiche un message d'erreur
     alert("Erreur..");
  }
}

// Association des événements dès que la page est chargée
function initialisation() {
  let form = document.getElementById('formulaire');
  form.addEventListener('submit', gererSubmit);
}

addEventListener('load', initialisation);

6 : Techniques de validation de formulaires

Définition

La validation de formulaires consiste à vérifier que les données saisies par l'utilisateur respectent certaines règles avant de les traiter.

Contexte d'utilisation

Il existe deux approches principales : la validation HTML intégrée et la validation JavaScript personnalisée.

Validation HTML

La validation HTML repose sur des attributs HTML5 comme required, pattern, minlength, maxlength, type, etc.

Avantages :

  • Simple à implémenter

  • Pas besoin de JavaScript

Inconvénients :

  • Limité aux règles prédéfinies
  • Empêche l'utilisation avancée de JavaScript (il faudra désactiver la validation HTML pour utiliser pleinement JavaScript)

Note : Pour ce cours, nous éviterons la validation HTML afin de pouvoir utiliser pleinement JavaScript.

Validation par JavaScript

La validation JavaScript implique l'écriture de fonctions personnalisées déclenchées lors d'événements comme submit, input, etc.

Avantages :

  • Validation plus complexe et personnalisable
  • Rétroaction en temps réel
  • Peut être combiné avec des bibliothèques tierces

Inconvénients :

  • Nécessite des compétences en programmation
  • Peut augmenter la complexité du code
  • Validation côté client peut être contournée ; toujours valider côté serveur

Validation en temps réel

Voici un exemple de validation JavaScript pour un formulaire avec 3 champs (nom, email, message) validés en temps réel :

html
<form id="contact-form" novalidate>
  <label for="name">Nom :</label>
  <input type="text" id="name" name="name" required>
  
  <label for="email">Email :</label>
  <input type="email" id="email" name="email" required>
  
  <label for="message">Message :</label>
  <textarea id="message" name="message" required></textarea>
  
  <button type="submit">Envoyer</button>
</form>
javascript

function validateName() {

    let nameInput = document.getElementById('name');

    if (nameInput.value === '') {
        alert("Le champ nom est requis.");
        return false;
    } else {
        return true;
    }
}

function validateMessage() {
    let messageInput = document.getElementById('message');



    if (messageInput.value === '') {
        alert("Le champ message est requis.");
        return false;
    } else {
        return true;
    }
}

function validateEmail() {

    let emailInput = document.getElementById('email');

    // On peut utiliser une fonction dédiée pour valider le format du courriel, si cette logique
    // est plus complexe. Ça permet la réutilisation de la logique de validation du format du courriel à différents endroits dans l'application, sans devoir dupliquer le code.
    if (!validateEmailFormat(emailInput.value)) {
        alert("Le format du courriel est invalide.");
        return false;
    } else {
        return true;
    }
}

/* Cette fonction est utilisée pour valider le courriel */
function validateEmailFormat(email) {

    // Logique d'un courriel valide. Attention, ça prendrait beaucoup plus que juste ce critère dans un cas réél

    // Si la chaine contient un @
    if (email.includes('@')) {
        return true;
    }
    else {
        return false;
    }
}

function gererSoumissionFormulaire(event) {

    // Première chose à faire : Empêcher la soumission du formulaire
    event.preventDefault();

    // Ensuite, on peut réutiliser les fonctions de validation en temps réel pour valider les champs du formulaire avant de le soumettre : pas besoin de refaire toute la logique de validation car elle existe déjà, mais elle est déclenchée à chaque fois que l'utilisateur modifie les champs.

    // Critères de validation 
    if (validateName() && validateEmail() && validateMessage()) {
        // Si on voudrait soummettre le formulaire à un serveur, c'est ici que ça se ferait
        // event.target.submit(); 

        // Si on veut simplement valider le formulaire, sans le soumettre à un serveur, on peut afficher un message de succès ou faire d'autres actions, etc.
        alert("Formulaire validé avec succès !");
        // Autres actions, par exemple vider les champs du formulaire, rediriger vers une autre page, etc.
        let form = document.getElementById('contact-form');
        form.reset();
    }
    else {
        // Dans ce cas-ci, les messages d'erreur sont déjà affichés par les fonctions de validation, 
        // donc on n'a pas besoin de faire quoi que ce soit d'autre ici.
        // Sinon, il aurait fallu afficher un message d'erreur global pour indiquer que 
        // le formulaire n'est pas valide, ou faire du focus sur le premier champ invalide, etc.
    }
}

function initialisation() {

    // Récupérer le formulaire
    const form = document.getElementById('contact-form');

    // Attraper la soumission du formulaire par l'événement submit afin de pouvoir le contrôler et éviter que la page soit automatiquement rechargée
    form.addEventListener('submit', gererSoumissionFormulaire);

    const nameInput = document.getElementById('name');
    const emailInput = document.getElementById('email');
    const messageInput = document.getElementById('message');

    // Exemple : évémenent d'entrée (input) pour valider les champs en temps réel, à chaque fois que l'utilisateur modifie les champs du formulaire
    nameInput.addEventListener('input', validateName);

    // Exemple : un évévnement de sortie du champs (blur) pour valider les champs lorsque l'utilisateur quitte le champ, 
    // si on ne veut pas valider à chaque modification du champ
    emailInput.addEventListener('blur', validateEmail);

    // Exemple : évémenent d'entrée (input)
    messageInput.addEventListener('input', validateMessage);
}

addEventListener('load', initialisation);

Exercices pratiques

Voir exercice 2

Exercices pratiques

Exercice 1 : Manipulation d'éléments et gestion d'événements

Objectif : Mettre en pratique les notions des théories 1, 2 et 3 (accès aux éléments du DOM, manipulation du contenu, gestion des événements et usage de event/target).

Consignes

  1. Utilise le code HTML de départ ci-dessous. Il contient 3 divs et une section, chacun avec un ID unique.
  2. Associe la même fonction gererClick aux trois divs pour gérer l'événement click.
  3. Lorsqu'une div est cliquée, insère dynamiquement dans la section le texte de la div cliquée. Assure-toi également que la class de la section soit la même que celle de la div cliquée (rouge, vert ou bleu).
  4. La fonction gererClick doit utiliser l'objet event et sa propriété currentTarget pour détecter automatiquement la div cliquée (ne pas utiliser getElementById pour retrouver la div cliquée).

Code HTML et CSS de départ

css
/* Code CSS à utiliser dans vos fichiers CSS pour cet exercice */
.rouge {
    background-color: red;
    color: white;
    padding: 10px;
}
.vert {
    background-color: green;
    color: white;
    padding: 10px;
}
.bleu {
    background-color: blue;
    color: white;
    padding: 10px;
}
html
// Code HTML à utiliser dans vos fichiers HTML pour cet exercice
<div id="div1" class="rouge">Texte de la première div</div>
<div id="div2" class="vert">Texte de la deuxième div</div>
<div id="div3" class="bleu">Texte de la troisième div</div>
<section id="zoneResultat"></section>

JavaScript à compléter

javascript
// TODO

Exercice 2 : Valider un formulaire simple

Objectif : Créer un formulaire avec validation JavaScript en temps réel, sans validation HTML native.

Consignes

  1. Crée un formulaire contenant trois champs : nom, prénom et âge.
  2. Le formulaire doit avoir l'attribut novalidate pour désactiver la validation HTML native.
  3. Valide que :
    • Le nom et le prénom ne sont pas vides.
    • L'âge est un nombre entre 1 et 100 inclusivement.
  4. La validation doit être réalisée en temps réel : dès que l'utilisateur sort d'un champ (événement blur).
  5. Si un champ est invalide, il doit être mis en surbrillance (ex : bordure rouge) sans utiliser alert.
    1. Attention, si il est valide, il doit revenir à son style normal (ex : bordure noire).
  6. Prévoyez une section dédiée sous le formulaire pour afficher dynamiquement le message d'erreur correspondant au champ en erreur.
    1. Si l'erreur concerne le champ nom, afficher "Le champ nom est requis."
    2. Si l'erreur concerne le champ prénom, afficher "Le champ prénom est requis."
    3. Si l'erreur concerne le champ âge, afficher "Le champ âge doit être un nombre entre 1 et 100."
  7. Si le formulaire est valide, afficher un message de succès dans la section dédiée : "Formulaire validé avec succès !" en VERT.
  8. Ne pas oublier d'empêcher le comportement par défaut du formulaire (empêche la soumission automatique lors du clic sur "Envoyer").

Exemple de structure HTML de départ

html
<form id="formulaire" action="#" novalidate>
    <label for="nom">Nom :</label>
    <input type="text" id="nom" name="nom">

    <label for="prenom">Prénom :</label>
    <input type="text" id="prenom" name="prenom">

    <label for="age">Âge :</label>
    <input type="text" id="age" name="age">

    <button type="submit">Envoyer</button>
</form>
<section id="erreur"></section>

Corrigés

Corrigé Exercice 1

javascript
function gererClick(event) {
    // Récupérer la div cliquée via event.currentTarget
    let divCliquee = event.currentTarget;
    
    // Récupérer la section zoneResultat
    let zoneResultat = document.getElementById("zoneResultat");
    
    // Insérer le texte de la div cliquée dans la section
    zoneResultat.textContent = divCliquee.textContent;
    
    // Appliquer la même classe à la section que celle de la div cliquée
    zoneResultat.className = divCliquee.className;
}

function initialisation() {
    // Récupérer les trois divs
    let div1 = document.getElementById("div1");
    let div2 = document.getElementById("div2");
    let div3 = document.getElementById("div3");
    
    // Attacher la fonction gererClick à l'événement click de chaque div
    div1.addEventListener("click", gererClick, false);
    div2.addEventListener("click", gererClick, false);
    div3.addEventListener("click", gererClick, false);
}

addEventListener("load", initialisation);

Vérification des connaissances

Question 1

Quelle méthode utilisez-vous pour accéder à un élément HTML par son ID ?

Réponse

La méthode getElementById(ID) permet de récupérer une référence à un élément HTML à partir de son ID.

javascript
let monElement = document.getElementById("mon-element");

Question 2

Quelle est la différence entre textContent et value ?

Réponse

textContent récupère ou modifie le texte brut d'un élément HTML, tandis que value est utilisé pour les éléments de formulaire comme input, textarea, select pour obtenir leur valeur actuelle.

javascript
// Pour un paragraphe
let text = document.getElementById("p1").textContent;

// Pour un input
let valeur = document.getElementById("nom").value;

Question 3

Comment empêcher la soumission par défaut d'un formulaire en JavaScript ?

Réponse

En utilisant event.preventDefault() dans le gestionnaire d'événement submit du formulaire.

javascript
function gererSoumission(event) {
    event.preventDefault();
    // Validation et traitement
}

form.addEventListener('submit', gererSoumission);