Gestion des Formulaires avec JavaScript Vanilla : Aucun Framework Requis

Les formulaires constituent l’épine dorsale de l’interaction utilisateur sur le web. Bien que les frameworks comme React et Vue offrent des abstractions pratiques, comprendre comment gérer les formulaires avec JavaScript vanilla vous donne un contrôle total et élimine les dépendances inutiles.
Ce guide vous accompagne à travers tout ce que vous devez savoir sur la gestion native des formulaires en JavaScript—de la sélection d’éléments et la capture de valeurs à la validation des entrées et au traitement des soumissions.
Points Clés à Retenir
- JavaScript vanilla fournit tous les outils nécessaires pour une gestion complète des formulaires sans frameworks
- Utilisez
event.preventDefault()
pour contrôler le comportement de soumission des formulaires - Tirez parti de la validation par contraintes HTML5 pour une validation de base avec un minimum de code
- Implémentez une validation en temps réel avec les événements
input
etblur
pour une meilleure expérience utilisateur - L’API FormData simplifie la collecte et le traitement des valeurs de formulaire
- Considérez toujours l’accessibilité lors de l’implémentation de validation personnalisée de formulaires
Gestion de Base des Formulaires avec JavaScript
Commençons par un formulaire HTML simple :
<form id="signup-form">
<div>
<label for="username">Username:</label>
<input type="text" id="username" name="username">
</div>
<div>
<label for="email">Email:</label>
<input type="email" id="email" name="email">
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" name="password">
</div>
<button type="submit">Sign Up</button>
</form>
Sélection des Éléments de Formulaire
Vous pouvez accéder à un formulaire et à ses éléments de plusieurs façons :
// Sélection par ID (recommandé pour des formulaires spécifiques)
const form = document.getElementById('signup-form');
// Sélection avec querySelector
const form = document.querySelector('#signup-form');
// Accès à la collection des formulaires
const forms = document.forms;
const signupForm = forms['signup-form']; // par id/nom
const firstForm = forms[0]; // par index
Capture de l’Événement de Soumission
Pour traiter la soumission du formulaire, ajoutez un écouteur d’événement au formulaire :
const form = document.getElementById('signup-form');
form.addEventListener('submit', function(event) {
// Empêcher la soumission par défaut du formulaire
event.preventDefault();
// Traiter les données du formulaire ici
console.log('Formulaire soumis !');
});
La méthode preventDefault()
empêche le navigateur de soumettre le formulaire et d’actualiser la page, vous donnant le contrôle sur ce qui se passe ensuite.
Accès aux Valeurs des Champs de Saisie
Il existe plusieurs façons d’accéder aux valeurs des champs de saisie :
Méthode 1 : Accès aux Éléments Individuels
form.addEventListener('submit', function(event) {
event.preventDefault();
// Obtenir les valeurs des éléments individuels du formulaire
const username = document.getElementById('username').value;
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
console.log(username, email, password);
});
Méthode 2 : Utilisation de form.elements
La propriété elements
fournit l’accès à tous les contrôles du formulaire :
form.addEventListener('submit', function(event) {
event.preventDefault();
// Accès via la collection elements
const username = form.elements.username.value;
const email = form.elements.email.value;
const password = form.elements.password.value;
console.log(username, email, password);
});
Méthode 3 : Utilisation de l’API FormData
L’API FormData
fournit une façon propre de capturer toutes les valeurs du formulaire :
form.addEventListener('submit', function(event) {
event.preventDefault();
// Créer un objet FormData à partir du formulaire
const formData = new FormData(form);
// Accéder aux valeurs individuelles
const username = formData.get('username');
const email = formData.get('email');
// Convertir en objet ordinaire
const formObject = Object.fromEntries(formData);
console.log(formObject); // {username: '...', email: '...', password: '...'}
});
Validation de Formulaire avec les Contraintes HTML5
Le HTML5 moderne fournit des attributs de validation intégrés qui fonctionnent sans JavaScript :
<form id="signup-form">
<div>
<label for="username">Username:</label>
<input type="text" id="username" name="username" required minlength="3">
</div>
<div>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required minlength="8"
pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).*$">
<small>Le mot de passe doit contenir au moins 8 caractères, incluant majuscules, minuscules et chiffres</small>
</div>
<button type="submit">Sign Up</button>
</form>
Les attributs de validation courants incluent :
required
: Le champ doit être rempliminlength
/maxlength
: Longueur minimale/maximale du textemin
/max
: Valeurs minimales/maximales pour les entrées numériquespattern
: Motif d’expression régulière à respectertype="email"
: Valide le format d’emailtype="url"
: Valide le format d’URL
Exploitation de l’API de Validation par Contraintes
JavaScript peut accéder au système de validation intégré du navigateur :
form.addEventListener('submit', function(event) {
// Vérifier si le formulaire est valide en utilisant l'API de Validation par Contraintes
if (!form.checkValidity()) {
// Le formulaire est invalide - laisser le navigateur gérer l'affichage des erreurs
return;
}
// Si nous arrivons ici, le formulaire est valide
event.preventDefault();
// Traiter les données valides du formulaire
console.log('Le formulaire est valide, traitement des données...');
});
Vous pouvez également vérifier la validité d’entrées spécifiques :
const emailInput = document.getElementById('email');
// Vérifier si l'email est valide
if (emailInput.validity.valid) {
console.log('L\'email est valide');
} else {
// Vérifier les échecs de validation spécifiques
if (emailInput.validity.typeMismatch) {
console.log('Le format de l\'email est incorrect');
}
if (emailInput.validity.valueMissing) {
console.log('L\'email est requis');
}
}
Validation Personnalisée et Messages d’Erreur
Bien que la validation HTML5 soit pratique, vous avez souvent besoin de logique de validation personnalisée et de messages d’erreur :
form.addEventListener('submit', function(event) {
event.preventDefault();
const username = document.getElementById('username');
const email = document.getElementById('email');
const password = document.getElementById('password');
// Effacer les messages d'erreur précédents
clearErrors();
let isValid = true;
// Validation personnalisée du nom d'utilisateur
if (username.value.trim() === '') {
displayError(username, 'Le nom d\'utilisateur est requis');
isValid = false;
} else if (username.value.length < 3) {
displayError(username, 'Le nom d\'utilisateur doit contenir au moins 3 caractères');
isValid = false;
}
// Validation personnalisée de l'email
if (!isValidEmail(email.value)) {
displayError(email, 'Veuillez saisir une adresse email valide');
isValid = false;
}
// Validation personnalisée du mot de passe
if (password.value.length < 8) {
displayError(password, 'Le mot de passe doit contenir au moins 8 caractères');
isValid = false;
} else if (!/[A-Z]/.test(password.value)) {
displayError(password, 'Le mot de passe doit contenir au moins une lettre majuscule');
isValid = false;
}
// Si valide, traiter le formulaire
if (isValid) {
console.log('Le formulaire est valide, soumission...');
// Soumettre les données du formulaire
}
});
function isValidEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
function displayError(input, message) {
const formControl = input.parentElement;
const errorElement = document.createElement('div');
errorElement.className = 'error-message';
errorElement.textContent = message;
formControl.appendChild(errorElement);
input.classList.add('error-input');
}
function clearErrors() {
document.querySelectorAll('.error-message').forEach(error => error.remove());
document.querySelectorAll('.error-input').forEach(input => {
input.classList.remove('error-input');
});
}
Validation en Temps Réel avec les Événements Input
Pour une meilleure expérience utilisateur, validez les entrées pendant que les utilisateurs tapent :
const emailInput = document.getElementById('email');
emailInput.addEventListener('input', function() {
if (this.value && !isValidEmail(this.value)) {
this.setCustomValidity('Veuillez saisir une adresse email valide');
} else {
this.setCustomValidity('');
}
});
function isValidEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
L’événement input
se déclenche chaque fois que l’utilisateur modifie la valeur, tandis que l’événement change
se déclenche lorsque l’entrée perd le focus après avoir été modifiée.
Gestion des Différents Types d’Entrée
Boutons Radio
<div>
<p>Plan d'abonnement :</p>
<label>
<input type="radio" name="plan" value="free" checked> Gratuit
</label>
<label>
<input type="radio" name="plan" value="premium"> Premium
</label>
</div>
// Obtenir la valeur du bouton radio sélectionné
const selectedPlan = document.querySelector('input[name="plan"]:checked').value;
// Écouter les changements
document.querySelectorAll('input[name="plan"]').forEach(radio => {
radio.addEventListener('change', function() {
console.log('Plan sélectionné :', this.value);
});
});
Cases à Cocher
<div>
<p>Centres d'intérêt :</p>
<label>
<input type="checkbox" name="interests" value="javascript"> JavaScript
</label>
<label>
<input type="checkbox" name="interests" value="html"> HTML
</label>
<label>
<input type="checkbox" name="interests" value="css"> CSS
</label>
</div>
// Obtenir toutes les valeurs cochées
function getSelectedInterests() {
const checkboxes = document.querySelectorAll('input[name="interests"]:checked');
const values = Array.from(checkboxes).map(cb => cb.value);
return values;
}
// Lors de la soumission du formulaire
form.addEventListener('submit', function(event) {
event.preventDefault();
const interests = getSelectedInterests();
console.log('Centres d\'intérêt sélectionnés :', interests);
});
Listes Déroulantes Select
<div>
<label for="country">Pays :</label>
<select id="country" name="country">
<option value="">Sélectionnez un pays</option>
<option value="us">États-Unis</option>
<option value="ca">Canada</option>
<option value="uk">Royaume-Uni</option>
</select>
</div>
// Obtenir la valeur sélectionnée
const country = document.getElementById('country').value;
// Écouter les changements
document.getElementById('country').addEventListener('change', function() {
console.log('Pays sélectionné :', this.value);
});
Exemple Complet de Traitement de Formulaire
Rassemblons tout dans un exemple complet :
document.addEventListener('DOMContentLoaded', function() {
const form = document.getElementById('signup-form');
// Ajouter la validation en temps réel
setupRealTimeValidation();
form.addEventListener('submit', function(event) {
event.preventDefault();
if (validateForm()) {
// Créer un objet avec les données du formulaire
const formData = new FormData(form);
const userData = Object.fromEntries(formData);
// Ici vous enverriez typiquement les données à un serveur
console.log('Soumission des données utilisateur :', userData);
// Simuler un appel API
submitFormData(userData)
.then(response => {
showSuccessMessage('Compte créé avec succès !');
form.reset();
})
.catch(error => {
showErrorMessage('Échec de la création du compte. Veuillez réessayer.');
});
}
});
function validateForm() {
// Effacer les erreurs précédentes
clearErrors();
let isValid = true;
const username = form.elements.username;
const email = form.elements.email;
const password = form.elements.password;
// Valider le nom d'utilisateur
if (username.value.trim() === '') {
displayError(username, 'Le nom d\'utilisateur est requis');
isValid = false;
} else if (username.value.length < 3) {
displayError(username, 'Le nom d\'utilisateur doit contenir au moins 3 caractères');
isValid = false;
}
// Valider l'email
if (email.value.trim() === '') {
displayError(email, 'L\'email est requis');
isValid = false;
} else if (!isValidEmail(email.value)) {
displayError(email, 'Veuillez saisir une adresse email valide');
isValid = false;
}
// Valider le mot de passe
if (password.value === '') {
displayError(password, 'Le mot de passe est requis');
isValid = false;
} else if (password.value.length < 8) {
displayError(password, 'Le mot de passe doit contenir au moins 8 caractères');
isValid = false;
} else if (!/[A-Z]/.test(password.value) || !/[a-z]/.test(password.value) || !/[0-9]/.test(password.value)) {
displayError(password, 'Le mot de passe doit inclure majuscules, minuscules et chiffres');
isValid = false;
}
return isValid;
}
function setupRealTimeValidation() {
const inputs = form.querySelectorAll('input');
inputs.forEach(input => {
input.addEventListener('input', function() {
// Effacer l'erreur quand l'utilisateur commence à taper
const errorElement = this.parentElement.querySelector('.error-message');
if (errorElement) {
errorElement.remove();
this.classList.remove('error-input');
}
});
});
// Validation spécifique à l'email
form.elements.email.addEventListener('blur', function() {
if (this.value && !isValidEmail(this.value)) {
displayError(this, 'Veuillez saisir une adresse email valide');
}
});
}
// Fonctions utilitaires
function isValidEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
function displayError(input, message) {
const formControl = input.parentElement;
const errorElement = document.createElement('div');
errorElement.className = 'error-message';
errorElement.textContent = message;
formControl.appendChild(errorElement);
input.classList.add('error-input');
}
function clearErrors() {
document.querySelectorAll('.error-message').forEach(error => error.remove());
document.querySelectorAll('.error-input').forEach(input => {
input.classList.remove('error-input');
});
}
function showSuccessMessage(message) {
const messageElement = document.createElement('div');
messageElement.className = 'success-message';
messageElement.textContent = message;
form.parentElement.insertBefore(messageElement, form);
// Supprimer après 3 secondes
setTimeout(() => {
messageElement.remove();
}, 3000);
}
function showErrorMessage(message) {
const messageElement = document.createElement('div');
messageElement.className = 'error-banner';
messageElement.textContent = message;
form.parentElement.insertBefore(messageElement, form);
// Supprimer après 3 secondes
setTimeout(() => {
messageElement.remove();
}, 3000);
}
// Simuler une soumission API
function submitFormData(data) {
return new Promise((resolve, reject) => {
// Simuler une requête réseau
setTimeout(() => {
// Taux de succès de 90% pour la démo
if (Math.random() > 0.1) {
resolve({ success: true, message: 'Utilisateur créé' });
} else {
reject({ success: false, message: 'Erreur serveur' });
}
}, 1500);
});
}
});
Considérations d’Accessibilité des Formulaires
Lors de la gestion des formulaires avec JavaScript, assurez-vous qu’ils restent accessibles :
- Maintenir la gestion du focus : Lors de l’affichage d’erreurs, définir le focus sur le premier champ invalide
- Utiliser les attributs ARIA : Ajouter
aria-invalid="true"
aux champs invalides - Associer les messages d’erreur : Utiliser
aria-describedby
pour connecter les entrées avec leurs messages d’erreur - Fournir des instructions claires : Utiliser les éléments
<label>
et des messages d’erreur descriptifs - Supporter la navigation au clavier : S’assurer que tous les contrôles de formulaire sont accessibles au clavier
Exemple de gestion d’erreur accessible :
function displayError(input, message) {
const formControl = input.parentElement;
const errorId = `${input.id}-error`;
const errorElement = document.createElement('div');
errorElement.id = errorId;
errorElement.className = 'error-message';
errorElement.textContent = message;
formControl.appendChild(errorElement);
// Ajouter les attributs d'accessibilité
input.setAttribute('aria-invalid', 'true');
input.setAttribute('aria-describedby', errorId);
// Définir le focus sur la première entrée invalide
if (!document.querySelector('.error-input')) {
input.focus();
}
input.classList.add('error-input');
}
FAQ
Utilisez la méthode reset intégrée sur l'élément formulaire : document.getElementById('myForm').reset();
Utilisez la méthode checkValidity de l'API de Validation par Contraintes : const isValid = form.checkValidity();
Pour soumettre des données de formulaire de manière asynchrone, utilisez l'API Fetch avec l'objet FormData. D'abord, créez une instance FormData à partir de votre formulaire. Ensuite, envoyez-la en utilisant fetch avec la méthode POST. Assurez-vous de gérer la réponse et d'intercepter toute erreur lors de la soumission.
Pour gérer les téléchargements de fichiers, accédez à la propriété files de l'élément input file, récupérez le fichier sélectionné, et ajoutez-le à un objet FormData avant de le soumettre en utilisant fetch ou une autre méthode.
L'événement `input` se déclenche chaque fois que la valeur d'entrée change, tandis que l'événement `change` ne se déclenche que lorsque l'entrée perd le focus et que la valeur a changé depuis qu'elle a obtenu le focus.
Pour ajouter dynamiquement des champs de formulaire, créez de nouveaux éléments input en utilisant document.createElement, définissez leur type et nom, et ajoutez-les à un élément conteneur dans le formulaire.
Conclusion
En maîtrisant la gestion des formulaires avec JavaScript vanilla, vous obtenez un contrôle total sur vos formulaires sans dépendre de bibliothèques externes. Cette approche réduit les dépendances, améliore les performances et approfondit votre compréhension du fonctionnement réel des formulaires web.