Comment envoyer des données de formulaire HTML avec JavaScript fetch()

HTML form submit fetch javascript tutorial showing code editor with fetch API call and form submission flow

Si tu as déjà créé un formulaire de contact et observé le rechargement complet de la page après qu'un utilisateur clique sur "Envoyer", tu sais déjà à quel point cette expérience peut être frustrante. En utilisant les techniques HTML form submit fetch javascript, tu peux envoyer les données du formulaire vers un endpoint backend en arrière-plan, maintenir l'utilisateur sur la même page, et afficher un message de succès ou d'erreur propre sans aucun rechargement complet de page. Ce tutoriel te guide à travers chaque étape, de l'écriture du HTML de base jusqu'à pointer ton appel fetch() vers un endpoint Sendform afin que tes soumissions arrivent directement dans ta boîte mail ou ton workflow connecté.

Points clés :

  • L'API Fetch te permet de soumettre des données de formulaire sans rechargement de page, offrant une expérience plus fluide aux utilisateurs.
  • Capturer l'événement submit et appeler preventDefault() est la base de tout pattern de soumission de formulaire ajax.
  • Sendform fournit une URL d'endpoint prête à l'emploi, tu n'as donc besoin d'aucun code backend pour recevoir et stocker les soumissions.
  • Une gestion appropriée des réponses (afficher des retours de succès ou d'erreur) est aussi importante que d'envoyer correctement les données.

Pourquoi utiliser fetch() au lieu d'une soumission de formulaire par défaut

Le comportement par défaut de soumission de formulaire du navigateur fait exactement une chose : il sérialise les champs du formulaire, envoie une requête POST (ou GET) vers l'URL action, puis charge la réponse que le serveur retourne. Cela signifie que l'utilisateur voit un flash blanc, perd sa position de défilement, et attend qu'une nouvelle page se charge. Sur une connexion lente, cela peut sembler cassé.

L'API Fetch résout ce problème en effectuant des requêtes HTTP de manière programmatique, entièrement en JavaScript, sans navigation. Cela permet un pattern de soumission de formulaire sans rechargement de page qui maintient l'engagement des utilisateurs et te donne un contrôle total sur chaque aspect de l'expérience utilisateur, incluant les états de chargement, les retours de validation en ligne, et les bannières de succès animées.

Raisons pratiques supplémentaires de préférer fetch() :

  • Tu peux attacher des en-têtes personnalisés (par exemple, un token CSRF ou une clé d'autorisation) qu'un formulaire HTML simple ne peut pas envoyer.
  • Tu peux sérialiser les données en JSON, FormData, ou chaînes encodées URL selon ce que l'endpoint attend.
  • La gestion d'erreurs est explicite. Tu décides ce que signifie "échec" et comment le communiquer.
  • Cela fonctionne sur tout site statique, y compris ceux hébergés sur GitHub Pages, Netlify, ou un CDN, car la logique réside entièrement dans le navigateur.

Note : Si tu travailles avec un constructeur de site web comme Webflow, WordPress, ou Hugo, la même approche fetch() s'applique. Consulte notre guide sur comment intégrer Sendform avec ton constructeur de site web pour des conseils spécifiques à la plateforme.

Configuration de base du formulaire HTML

Avant d'écrire une seule ligne de JavaScript, tu as besoin d'un formulaire HTML bien structuré. Le détail clé ici est que tu n'as pas besoin d'un attribut action pointant quelque part, car JavaScript gérera la soumission. Tu veux cependant des attributs name significatifs sur chaque input - ceux-ci deviennent les clés de champ dans la charge utile soumise.

<form id="contact-form" novalidate>
  <div>
    <label for="name">Ton nom</label>
    <input type="text" id="name" name="name" required placeholder="Jane Smith">
  </div>

  <div>
    <label for="email">Adresse e-mail</label>
    <input type="email" id="email" name="email" required placeholder="[email protected]">
  </div>

  <div>
    <label for="message">Message</label>
    <textarea id="message" name="message" rows="5" required></textarea>
  </div>

  <button type="submit">Envoyer le message</button>

  <!-- Zone de retour -->
  <div id="form-feedback" aria-live="polite"></div>
</form>

Quelques points à noter dans ce balisage :

  • novalidate sur l'élément form désactive les bulles de validation native du navigateur, te donnant un contrôle total sur la messagerie d'erreur en JavaScript.
  • La div id="form-feedback" avec aria-live="polite" est où les messages de succès et d'erreur apparaîtront. L'attribut ARIA assure que les lecteurs d'écran annoncent automatiquement le retour.
  • Chaque input a à la fois un id (pour l'association du label) et un name (pour la charge utile du formulaire).

Capturer l'événement de soumission

La première étape dans toute soumission de formulaire javascript est d'intercepter le comportement par défaut du navigateur. Tu fais cela en écoutant l'événement submit sur l'élément form et en appelant immédiatement event.preventDefault().

const form = document.getElementById('contact-form');

form.addEventListener('submit', async function (event) {
  event.preventDefault(); // Stoppe la navigation de page par défaut

  // Validation basique côté client
  const name = form.elements['name'].value.trim();
  const email = form.elements['email'].value.trim();
  const message = form.elements['message'].value.trim();

  if (!name || !email || !message) {
    showFeedback('Merci de remplir tous les champs.', 'error');
    return;
  }

  // Procéder à l'envoi des données (section suivante)
  await submitForm({ name, email, message });
});

En séparant la logique de validation de l'appel réseau, tu maintiens le code lisible et facile à étendre. Le mot-clé async sur le gestionnaire d'événement te permet d'utiliser await à l'intérieur, ce qui fait que l'appel de données de formulaire Fetch API ressemble à du code synchrone et évite les chaînes de promesses profondément imbriquées.

Pointer fetch() vers un endpoint Sendform

C'est ici que le vrai travail se fait. Au lieu de construire ton propre serveur pour recevoir, stocker et transférer les soumissions de formulaire, tu peux utiliser Sendform comme ton backend. Après avoir créé un formulaire dans le tableau de bord Sendform, tu obtiens une URL d'endpoint unique. Cette URL est tout ce dont tu as besoin.

La fonction de soumission ci-dessous utilise l'API FormData pour construire la charge utile, que Sendform accepte nativement :

async function submitForm(data) {
  // Remplace cette URL par ton endpoint Sendform réel
  const SENDFORM_ENDPOINT = 'https://sendform.net/fr/YOUR_FORM_ID';

  const formData = new FormData();
  formData.append('name', data.name);
  formData.append('email', data.email);
  formData.append('message', data.message);

  try {
    const response = await fetch(SENDFORM_ENDPOINT, {
      method: 'POST',
      body: formData,
    });

    if (response.ok) {
      showFeedback('Merci ! Ton message a été envoyé.', 'success');
      form.reset();
    } else {
      const errorData = await response.json().catch(() => ({}));
      const errorMsg = errorData.message || 'Quelque chose s\'est mal passé. Merci de réessayer.';
      showFeedback(errorMsg, 'error');
    }
  } catch (networkError) {
    showFeedback('Erreur réseau. Vérifie ta connexion et réessaie.', 'error');
  }
}

Décisions clés prises dans ce code :

  • Aucun en-tête Content-Type n'est défini manuellement. Quand tu passes un objet FormData comme body, le navigateur définit automatiquement la bonne limite multipart/form-data.
  • La vérification response.ok couvre tous les codes de statut HTTP 2xx, pas seulement 200. C'est plus robuste que comparer response.status === 200.
  • Le try/catch externe capture les échecs au niveau réseau (erreurs DNS, état hors ligne) que response.ok ne verrait jamais.
Flux de soumission de formulaire JavaScript fetch pointant vers un endpoint Sendform

Gérer la réponse - Messages de succès et d'erreur

Envoyer les données n'est que la moitié du travail. Les utilisateurs ont besoin d'un retour immédiat et clair. La fonction d'aide showFeedback() référencée ci-dessus écrit un message dans la div de retour que tu as ajoutée au HTML :

function showFeedback(message, type) {
  const feedbackEl = document.getElementById('form-feedback');
  feedbackEl.textContent = message;
  feedbackEl.className = type === 'success' ? 'feedback-success' : 'feedback-error';
}

C'est intentionnellement minimal. Dans un vrai projet, tu pourrais remplacer textContent par un composant animé ou une bibliothèque de notifications toast, mais le pattern reste le même : mettre à jour le DOM basé sur le résultat de l'appel fetch().

Pour des scénarios plus avancés, comme rediriger vers une page de remerciement personnalisée ou déclencher une automatisation en aval après soumission, consulte notre article sur comment automatiser les workflows de formulaires avec des webhooks, Zapier et des APIs.

Bonnes pratiques et conseils

Faire fonctionner le code est une chose. Le livrer d'une manière qui tient en production en est une autre. Voici les conseils les plus importants à garder en tête :

  • Désactive le bouton de soumission pendant la requête. Définis button.disabled = true avant d'appeler fetch() et réactive-le dans un bloc finally. Cela empêche les soumissions en double si l'utilisateur clique plusieurs fois.
  • Montre un état de chargement. Change le texte du bouton en "Envoi en cours..." ou ajoute une classe de spinner pendant que la requête est en cours. Les utilisateurs qui ne voient aucun retour supposent souvent que rien ne s'est passé et cliquent à nouveau.
  • Valide aussi côté serveur. La validation côté client est pour l'expérience utilisateur. Sendform et tout service backend devraient traiter toutes les données entrantes comme non fiables.
  • Utilise HTTPS partout. Envoyer des données de formulaire via HTTP simple expose les entrées utilisateur en transit. Les endpoints Sendform sont HTTPS par défaut, mais assure-toi que ta propre page est aussi servie via HTTPS.
  • Ajoute une protection anti-spam. Un champ honeypot ou une intégration CAPTCHA réduit significativement les soumissions indésirables. Pour un regard plus approfondi sur ce sujet, consulte notre guide sur les bonnes pratiques de protection anti-spam pour les formulaires.
  • Teste délibérément le chemin d'erreur. Change temporairement l'URL d'endpoint vers quelque chose d'invalide et confirme que ton message d'erreur apparaît. La plupart des développeurs ne testent que le chemin heureux.
  • Garde l'URL d'endpoint hors du contrôle de version. Si ton projet est open source, stocke l'endpoint Sendform dans une variable d'environnement ou un fichier de config qui est listé dans .gitignore.

Utilisateurs de sites statiques : Si ton projet est un site Hugo, Eleventy, ou HTML simple sans serveur, l'approche fetch() décrite ici est la méthode recommandée. Lis plus dans notre guide de gestion de formulaires serverless pour sites statiques.

Conclusion

Remplacer une soumission de formulaire par défaut par un appel fetch() est l'une des améliorations les plus impactantes que tu puisses apporter à tout formulaire de contact ou de capture de leads. Le résultat est une expérience plus rapide et plus professionnelle qui maintient les utilisateurs sur ta page et te donne un contrôle total sur la messagerie de retour. Associe cela avec un endpoint Sendform et tu élimines entièrement le besoin de code côté serveur. Ton formulaire est en ligne, tes soumissions atteignent ta boîte mail, et tes utilisateurs ne voient jamais un rechargement de page choquant. Crée ton endpoint Sendform gratuit aujourd'hui et reçois ta première soumission en quelques minutes.

Questions fréquemment posées

Oui. Parce que fetch() s'exécute entièrement dans le navigateur, cela fonctionne sur les sites HTML statiques, les projets JAMstack, et toute plateforme qui sert du HTML. Tu n'as pas besoin de ton propre serveur. La seule exigence est un endpoint (comme une URL Sendform) qui peut recevoir la requête POST.

fetch() est le remplacement moderne de XMLHttpRequest. Il utilise les Promises, supporte async/await, et a une API plus propre. Pour les nouveaux projets, fetch() est toujours préféré. Les deux atteignent le même résultat de soumission de formulaire ajax, mais fetch() nécessite significativement moins de code répétitif.

Non. Quand tu passes un objet FormData comme body, le navigateur définit automatiquement le Content-Type à multipart/form-data et inclut la chaîne de limite correcte. Le définir manuellement casserait en fait la requête en omettant cette valeur de limite.

Inscris-toi sur Sendform, crée un nouveau formulaire dans le tableau de bord, et copie l'URL d'endpoint générée. Colle cette URL comme cible dans ton appel fetch(). Les soumissions seront transférées vers ton adresse e-mail configurée immédiatement.

Un échec réseau provoque le rejet de la Promise fetch(), qui est capturé par le bloc try/catch externe dans l'exemple de code. L'utilisateur voit le message "Erreur réseau" que tu as défini. La soumission n'est pas mise en file d'attente automatiquement ; l'utilisateur doit réessayer une fois la connectivité restaurée.