Mise en place de votre formulaire de contact avec Formspree et jQuery

Mise en place de votre formulaire de contact avec Formspree et jQuery
Categories:
Posté le

La gestion des formulaires, le plus courant est celui de contact, et un élément systématique et indispensable lors du développement d'un site web et notamment d'un site vitrine.

La qualité d'implémentation et la facilité d'utilisation sont des éléments primordiaux.

Qui n'a pas déjà été confronté à un formulaire incompréhensible avec une gestion des erreurs totalement inutiles ou pire l’échec de son envoi.

Échec qui a des impacts non seulement d'un point de vue de l'utilisateur mais également une perte d'opportunités business puisque la demande ne vous est jamais parvenue.

Les problèmes sont généralement des problèmes de gestion d'erreurs ou de configuration de l'hébergement du site qui n'envoie donc pas les mails. 

Nous allons voir ici un système qui permet de gérer tout types de formulaires et d'assurer non seulement la facilité d'utilisation mais également la bonne réception des mails.

Nous allons utiliser les technologies suivantes :

  • Formspree (tier gratuit), solution qui permet de gérer la soumission de formulaires de manière directe ou indirecte en utilisant l'API (au format json), méthode choisie ici. Puis d'envoyer un mail avec les informations du formulaire ou de faire un appel à Zappier ou d'autres applications afin de remplir par exemple un Google Sheets
  • jQuery (en version 3.4.1)
  • Bootstrap (en version 4.4.1)

Mise en place de Formspree :

La première chose à faire est donc de créer un compte sur Formspree : https://formspree.io/, puis de créer un formulaire depuis son interface.

La configuration du formulaire sera la suivante durant la phase de développement, à noter qu'il est important de spécifier la restriction de domaine sur un site en production :

Il faut ensuite récupérer l'unique id  (c'est l’identifiant qui va permettre à Fromspree de savoir de quel formulaire il s'agit) du formulaire :

Vous trouverez cette information dans la partie 'Intégration' de la configuration de votre formulaire sour la forme : https://formspree.io/---UNIQUE-ID---, en remplacent ---UNIQUE-ID--- par la valeur fournie par Formspree.

Mise en place du formulaire :

On va mettre en place un formulaire de contact qui servir d'exemple pour illustrer l'utilisation de Fromspree.

Les sources de l'article : https://github.com/Zenicheck/blog/tree/master/formspree-jquery

On a donc le fichier html suivant (il faut bien sûr remplacer ----UNIQUE-ID---- dans l'action du formulaire par l'identifiant du vôtre):

<!DOCTYPE html>
<html lang="fr">
<!-- index.html -->
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
        integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <title>Formulaire de contact avec Formspree et jQuery</title>
    <style>
        .required-label:after {
            content: " *";
            color: red;
        }
    </style>
</head>

<body class="bg-light">
    <div class="container">
        <div class="py-5 text-center">
            <h2>Nous contacter</h2>
        </div>
        <div class="row">
            <div class="col-md-12 order-md-1">
                <h4 class="mb-3">Un projet de création de site internet ? Une question ou une demande de devis ?</h4>
                <form class="needs-validation" id="contact-form" action="https://formspree.io/----UNIQUE-ID----" method="POST"
                    novalidate>
                    <div class="mb-3">
                        <label for="contactName" class="required-label">Nom & Prénom (& société)</label>
                        <input type="text" class="form-control" id="contactName" name="contactName" placeholder=""
                            required>
                        <div class="invalid-feedback">
                            Veuillez entrer votre nom
                        </div>
                    </div>

                    <div class="mb-3">
                        <label for="_replyto" class="required-label">E-mail</label>
                        <input type="email" class="form-control" id="_replyto" name="_replyto" placeholder="" required>
                        <div class="invalid-feedback">
                            Veullez entrer votre adresse e-mail
                        </div>
                    </div>

                    <div class="mb-3">
                        <label for="contactMessage" class="required-label">Votre message</label>
                        <textarea class="form-control" id="contactMessage" name="contactMessage" placeholder=""
                            required></textarea>
                        <div class="invalid-feedback">
                            Veulliez entrez votre message
                        </div>
                    </div>
                    <div class="custom-control custom-checkbox">
                        <input type="checkbox" class="custom-control-input" id="newsletter" name="newsletter">
                        <label class="custom-control-label" for="newsletter">S'inscire à la newsletter</label>
                    </div>
                    <hr class="mb-4">
                    <button class="btn btn-primary btn-lg btn-block" type="submit" id="submit-btn">Envoyer</button>
                </form>
            </div>
        </div>

        <footer class="my-5 pt-5 text-muted text-center text-small">
            <p class="mb-1">&copy; 2019-2020 <a href="https://zenicheck.com" target="_blank">ZENICHECK</a> | Réalisé par
                <a href="https://yanncarlen.com" target="_blank">Yann Carlen</a></p>
        </footer>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"
        integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
        integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
        crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
        integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
        crossorigin="anonymous"></script>
    <script src="/app.js"></script>
</body>

</html>

On va également utiliser le petit serveur HTTP par Python (ici en version 3) afin d'effectuer nos tests :

$ cat run.sh 
#!/bin/sh

python3 -m http.server 7890 

$ ./run.sh
Serving HTTP on 0.0.0.0 port 7890 ...

Vous pouvez ainsi vous rendre sur l'urlhttp://localhost:7890/ et constater le visuel suivant :

Le fichier HTML du formulaire fait référence à un fichier app.js nous allons donc le créer.

Gestion du formulaire avec jQuery :

/* app.js */
$(document).ready(function () {

    const contactForm = $('#contact-form');

    contactForm.length && contactForm.on("submit", function (e) {
        e.preventDefault();
        $('.contact-form-status').remove();
        const form = $(this);
        const route = form.attr('action');
        const btn = form.find('#submit-btn');

        const _replyto = form.find('input[name="_replyto"]');
        const contactName = form.find('input[name="contactName"]');
        const contactMessage = form.find('#contactMessage');
        const newsletter = form.find('#newsletter').prop('checked');

        removeClass([_replyto, contactName, contactMessage]);

        if (validateFields([_replyto, contactName, contactMessage]) !== undefined) {
            return false;
        }

        btn.prop('disabled', true);
        btn.html('Envoi en cours...');
        $.ajax({
            url: route,
            method: 'POST',
            contentType: 'application/json',
            data: JSON.stringify({
                _replyto: _replyto.val(),
                contactName: contactName.val(),
                contactMessage: contactMessage.val()
            }),
            dataType: 'json',
            processData: false,
            success: function () {
                if (newsletter) {
                    // call to newsletter api
                }
                btn.html('Envoyer');
                btn.prop('disabled', false);
                form.prepend('<div class="alert alert-success contact-form-status" role="alert">' +
                    'Message envoyé ! Je reviens vers vous au plus vite !</div>');
                contactForm.trigger('reset');
            },
            error: function () {
                btn.html('Renvoyer');
                btn.prop('disabled', false);
                form.prepend('<div class="alert alert-danger contact-form-status" role="alert">' +
                    'Erreur lors de l\'envoi du message !</div>');
            }
        });
        return false;
    });

    function validateFields(fields) {
        return fields.map(function (e) {
            const val = e.val();
            if (val == undefined || val == null || val == '') {
                e.addClass('is-invalid');
                return true;
            }
            return false;
        }).find(function (e) {
            return e == true;
        });
    }

    function removeClass(fields) {
        fields.map(function (e) {
            e.removeClass('is-invalid');
        });
    }

});

Le code se découpe donc en 4 parties principales :

  • on attache un listener à la soumission du formulaire #contact-form
  • la fonction validateFields qui va vérifier la valeur des différents champs et ajouter la class is-invalid sur les champs dont la valeur n'a pas été renseigné
  • la fonction removeClass qui va supprimer la class is-invalid afin d'effectuer une nouvelle vérification des données à chaque re-soumission de formulaire afin de supprimer les effets visuels des champs en erreur (visuel plus bas)
  • l'appel à l'api de Formspree grâce à un appel ajax de jQuery qui va envoyer la valeur des différents champs du formulaire, le tout au format json puis ajouter une alerte en cas de succès ou d'erreur. (visuel plus bas).

Visuel en cas de champs manquants :

Visuel en cas de succès de l'envoi :

Visuel en cas d'erreur retournée par l'API de Formspree :

Vous constaterez également la présence d'une checkbox 'S'inscrire à la Newsletter' et le bout de code suivant :

/* app.js */
/*
** ...
*/
  success: function () {
                if (newsletter) {
                    // call to newsletter api
                }
/*
** ...
*/

Cette checkbox nous permet de demander à l'utilisateur si oui ou non il souhaite s'inscrire à la newsletter et ainsi une fois l'envoi du formulaire exécuté de faire un appel à l'appel d'une API de newsletter (par exemple MailChimp, ...).

Sujet qui pourra par ailleurs faire l'occasion d'un prochain article.

Si vous souhaitez utiliser cette solution ou pour touts autres besoins concernant l'implémentation de formulaires ou développement web, n'hésitez pas à me contacter : https://www.yanncarlen.com/contact !

Les sources de l'article : https://github.com/Zenicheck/blog/tree/master/formspree-jquery