Soumettre des formulaires avec JavaScript (AJAX)
Disponible sur : tous les abonnements
Vous pouvez utiliser @formspree/ajax pour soumettre vos formulaires Formspree en JavaScript pur, sans avoir à écrire votre propre logique fetch, Axios ou jQuery.
La bibliothèque fonctionne avec les formulaires HTML standard et ajoute une gestion déclarative des formulaires via des attributs de données ou une petite API JavaScript. Elle gère automatiquement la soumission, l’état de chargement, les erreurs de validation et les messages de succès.
Comment ça fonctionne
@formspree/ajax vous offre une manière déclarative de configurer un formulaire. Au lieu d’écouter manuellement les événements de soumission et d’écrire votre propre logique de requête, vous annotez votre formulaire avec des attributs de données et l’initialisez avec votre identifiant de formulaire Formspree.
Par défaut, la bibliothèque gère :
- la soumission du formulaire
- l’état de chargement sur le bouton d’envoi
- les erreurs de validation au niveau des champs
- les erreurs au niveau du formulaire
- les messages de succès
- l’état de champ invalide avec
aria-invalid="true"
Voici comment l’implémenter dans votre projet :
Étape 1 : Configurer @formspree/ajax dans votre projet
Vous pouvez utiliser @formspree/ajax de deux manières selon votre configuration :
- Avec un bundler (ESM via npm/yarn)
- Sans bundler (balise script/CDN)
Option 1 : Utiliser un bundler (ESM)
Installez la bibliothèque :
npm install @formspree/ajax # via npm, or
yarn add @formspree/ajax # via yarn
Puis initialisez votre formulaire en JavaScript :
import { initForm } from '@formspree/ajax';
initForm({
formElement: '#contact-form',
formId: 'YOUR_FORM_ID',
});
Assurez-vous que l’ID de votre élément de formulaire HTML correspond à l’ID que vous passez dans la propriété formElement. Remplacez YOUR_FORM_ID par l’identifiant de formulaire que vous recevez dans le tableau de bord Formspree.
Option 2 : Utiliser une balise script (sans étape de build)
Si vous n’utilisez pas de bundler, ajoutez cet extrait avant la balise </body> fermante :
<script>
window.formspree =
window.formspree ||
function () {
(formspree.q = formspree.q || []).push(arguments);
};
formspree(
'initForm',
{ formElement: '#contact-form', formId: 'YOUR_FORM_ID' }
);
</script>
<script src="https://unpkg.com/@formspree/ajax@1" defer></script>
Comme pour la première option, assurez-vous que l’ID de votre formulaire HTML correspond à celui que vous passez dans formElement. Remplacez YOUR_FORM_ID par l’identifiant de formulaire reçu dans le tableau de bord Formspree.
Étape 2 : Créer votre formulaire
Une fois @formspree/ajax configuré dans votre projet, voici comment créer un formulaire :
<div data-fs-success></div>
<div data-fs-error></div>
<form id="contact-form">
<label for="email">Email</label>
<input type="email" id="email" name="email" data-fs-field />
<span data-fs-error="email"></span>
<button type="submit" data-fs-submit-btn>Send</button>
</form>
Veillez à ce que la valeur de l’attribut
idde votre formulaire corresponde à l’ID passé commeformIddans l’appelinitFormà l’étape précédente.
La bibliothèque soumettra automatiquement le formulaire à Formspree, désactivera le bouton d’envoi pendant la requête, affichera les erreurs de validation et présentera un message de succès.
Attributs de données
La bibliothèque @formspree/ajax propose quelques attributs qui vous permettent de contrôler le comportement du formulaire sans JavaScript supplémentaire.
data-fs-error="fieldName"
Utilisez cet attribut sur un élément <span> ou <div> pour afficher les erreurs de validation au niveau d’un champ.
<span data-fs-error="email"></span>
Si l’élément est vide, Formspree y injecte le message d’erreur de l’API. S’il contient déjà du contenu, ce contenu est affiché ou masqué selon l’état.
data-fs-error
Utilisez cet attribut sans valeur pour afficher les erreurs au niveau du formulaire.
<div data-fs-error></div>
Utile pour les erreurs de soumission générales qui ne sont pas liées à un champ spécifique.
data-fs-success
Utilisez cet attribut pour afficher un message de succès après la soumission.
<div data-fs-success></div>
Si l’élément est vide, le message par défaut est affiché. S’il contient déjà du contenu, ce contenu est utilisé à la place.
data-fs-field
Utilisez cet attribut sur les champs de formulaire qui doivent recevoir aria-invalid="true" en cas d’échec de validation.
<input type="email" name="email" data-fs-field />
La bibliothèque lit le nom du champ depuis l’attribut name de l’élément.
data-fs-submit-btn
Utilisez cet attribut sur le bouton d’envoi pour le désactiver pendant la soumission et le réactiver ensuite.
<button type="submit" data-fs-submit-btn>Send</button>
Comportement par défaut
Sans aucune personnalisation, la bibliothèque offre des comportements sensés par défaut :
- Le bouton d’envoi est désactivé pendant la soumission du formulaire.
- Les erreurs de champ s’affichent dans les éléments
data-fs-error="fieldName"correspondants. - Les champs invalides reçoivent
aria-invalid="true". - Un message de succès s’affiche dans l’élément
data-fs-success. - Un message d’erreur au niveau du formulaire s’affiche dans l’élément
data-fs-error. - S’il n’y a pas d’élément
data-fs-successet pas de gestionnaireonSuccesspersonnalisé, le formulaire est remplacé par un message « Thank you! ». - S’il y a un élément
data-fs-successmais pas de gestionnaireonSuccesspersonnalisé, le formulaire est réinitialisé après une soumission réussie. - Des styles par défaut de base sont injectés automatiquement.
Configuration avancée
La bibliothèque offre également des moyens de personnaliser davantage le comportement et l’apparence de votre formulaire.
Ajouter des données supplémentaires à chaque soumission
Vous pouvez utiliser l’option data pour ajouter des valeurs supplémentaires à chaque soumission. Ces valeurs peuvent être :
- des chaînes statiques
- des fonctions synchrones
- des fonctions asynchrones
Les valeurs undefined sont ignorées. Voici comment l’utiliser :
initForm({
formElement: '#my-form',
formId: 'YOUR_FORM_ID',
// This data will be added to every submission
data: {
source: 'landing-page',
referrer: () => document.referrer || undefined,
sessionId: async () => await fetchSessionId(),
},
});
Cela est utile pour associer des métadonnées comme des noms de campagne, des sources de référence ou des identifiants de session sans ajouter de champs masqués dans votre HTML.
Callbacks de cycle de vie
Vous pouvez vous connecter à différentes étapes du cycle de vie de la soumission.
initForm({
formElement: '#contact-form',
formId: 'YOUR_FORM_ID',
// Called when the form is initialized
onInit: (context) => {
console.log('Form initialized');
},
// Called before submission is sent.
onSubmit: (context) => {
console.log('Submitting form');
},
// Called on successful submission.
onSuccess: (context, result) => {
console.log('Submission succeeded', result);
},
// Called if validation errors are received from Formspree
onError: (context, error) => {
console.log('Validation error', error);
},
// Called if unexpected errors are received (e.g., network failure).
onFailure: (context, error) => {
console.log('Unexpected error', error);
},
});
L’objet context contient le formulaire actuel (HTMLFormElement), les détails du point de terminaison, le client et l’objet de configuration passé à initForm.
Ces callbacks peuvent être utilisés pour :
- Suivre des événements (analytics, conversions, abandons)
- Afficher une interface personnalisée (spinners, toasts, bannières)
- Rediriger après une soumission réussie
- Journaliser ou déboguer les requêtes et les échecs
- Gérer de manière personnalisée les erreurs de validation ou de formulaire
- Exécuter des effets secondaires avant ou après la soumission (ex. : sauvegarder un état, déclencher des workflows)
Rendu personnalisé
Vous pouvez remplacer le comportement d’interface par défaut en fournissant des méthodes de rendu personnalisées dans initForm(). Utile si vous voulez un contrôle total sur l’affichage des états de chargement, des erreurs et des messages de succès.
initForm({
formElement: '#contact-form',
formId: 'YOUR_FORM_ID',
enable: (context) => {},
disable: (context) => {},
renderFieldErrors: (context, error) => {},
renderSuccess: (context, message) => {},
renderFormError: (context, message) => {},
});
Méthodes disponibles
| Méthode | Moment d’exécution | Usages courants |
|---|---|---|
disable(context) | Au démarrage de la soumission | Ajouter un état de chargement, désactiver les boutons/champs |
enable(context) | Après la fin de la soumission | Supprimer les spinners, réactiver l’interface |
renderFieldErrors(context, error) | En cas d’erreurs de validation | Interface d’erreur personnalisée, erreurs groupées, toasts |
renderSuccess(context, message) | En cas de soumission réussie | Remplacer le formulaire, afficher un toast, rediriger |
renderFormError(context, message) | En cas d’erreurs au niveau du formulaire | Bannières d’erreur, alertes, messages centralisés |
Voici comment les utiliser :
initForm({
formElement: '#contact-form',
formId: 'YOUR_FORM_ID',
disable: ({ form }) => form.classList.add('loading'),
enable: ({ form }) => form.classList.remove('loading'),
renderSuccess: ({ form }, message) => {
form.innerHTML = `<p>${message}</p>`;
},
});
Styles
La bibliothèque inclut des styles par défaut pour les erreurs, les champs invalides et les messages de succès. Vous pouvez les remplacer par votre propre CSS.
[data-fs-error] {
color: #dc3455;
}
[data-fs-field][aria-invalid='true'] {
border-color: #dc3455;
}
[data-fs-success][data-fs-active] {
background: #de4dda;
}
[data-fs-error=''][data-fs-active] {
background: #f87dda;
color: #72c124;
}
Nettoyage
initForm() retourne un handle avec une méthode destroy(). Vous pouvez l’utiliser pour supprimer le comportement du formulaire si nécessaire.
const handle = initForm({
formElement: '#contact-form',
formId: 'YOUR_FORM_ID',
});
// Clean up when needed
handle.destroy();
Exemple ESM complet
Voici un exemple complet utilisant un formulaire HTML classique et @formspree/ajax avec un bundler. Commencez par initialiser le formulaire avec votre identifiant Formspree :
import { initForm } from '@formspree/ajax';
initForm({
formElement: '#contact-form',
formId: 'YOUR_FORM_ID',
});
Créez ensuite le formulaire HTML avec les attributs de données décrits ci-dessus :
<div data-fs-success></div>
<div data-fs-error></div>
<form id="contact-form">
<label for="email">Email</label>
<input type="email" id="email" name="email" data-fs-field />
<span data-fs-error="email"></span>
<label for="message">Message</label>
<textarea id="message" name="message" data-fs-field></textarea>
<span data-fs-error="message"></span>
<button type="submit" data-fs-submit-btn>Send</button>
</form>
Exemple avec balise script
Si vous souhaitez utiliser la bibliothèque sans étape de build, vous pouvez l’initialiser directement dans le navigateur :
<div data-fs-success></div>
<div data-fs-error></div>
<form id="my-form">
<label for="email">Email</label>
<input type="email" id="email" name="email" data-fs-field />
<span data-fs-error="email"></span>
<label for="message">Message</label>
<textarea id="message" name="message" data-fs-field></textarea>
<span data-fs-error="message"></span>
<button type="submit" data-fs-submit-btn>Submit</button>
</form>
<script>
window.formspree =
window.formspree ||
function () {
(formspree.q = formspree.q || []).push(arguments);
};
formspree('initForm', {
formElement: '#my-form',
formId: 'YOUR_FORM_ID',
});
</script>
<script src="https://unpkg.com/@formspree/ajax@1" defer></script>
Migration depuis du code AJAX manuel
Si vous avez précédemment soumis des formulaires avec du code fetch, Axios ou jQuery personnalisé, @formspree/ajax vous offre une alternative plus simple. Au lieu de gérer manuellement :
- l’écoute des événements de soumission
- la sérialisation des données du formulaire
- l’envoi des requêtes
- l’analyse des erreurs de validation
- la mise à jour du DOM pour les états de succès et d’échec
Vous pouvez initialiser la bibliothèque une seule fois et la laisser gérer tout cela.
Note sur les frameworks
Cette bibliothèque est conçue pour le JavaScript vanilla et les formulaires HTML standard. Si vous utilisez React, consultez plutôt notre bibliothèque React.