Insérer un formulaire dans une modale avec Symfony et MaterializeCSS

Quand on débute le développement Web, une des choses assez difficile à comprendre est le fonctionnement des fenêtres modale. Cette question m'a été posé plusieurs fois, c'est pour cette raison que j'ai décidé de faire un article.

Principe de fonctionnement

Principe de fonctionnement des fenêtres modales

la fenêtre modale est déjà intégrée dans la page Web mais n'est simplement pas encore affichée. Voici un exemple de code html avec materializecss :

<!-- Bouton servant à activer la modale -->
<a class="waves-effect waves-light btn modal-trigger" href="#modal1">Modal</a>

<!-- Structure de la modale -->
<div id="modal1" class="modal">
<div class="modal-content">
<h4>Modal Header</h4>
A bunch of text

</div>
<div class="modal-footer"><a class="modal-close waves-effect waves-green btn-flat" href="#!">Agree</a></div>
</div>

On peut donc voir qu'une fenêtre modale est composée de deux parties: la structure et le lien permettant de l'activer.

Quand on clique sur le lien elle s'affiche mais est vide. Il faut donc à ce moment là effectuer un appel AJAX pour la remplir. (afficher le formulaire).

Exemple avec Symfony

Dans cet exemple, nous avons une entité « compétition » et une entité « inscrit » . Il y a une relation one to many: 1 compétition peut avoir plusieurs inscrits.
Voici la vue twig:
Le lien d'activation:
<a data-target="{{ path('competition-inscription', {'id': competition.id}) }}" data-tooltip="voir"
   class="tooltipped modal-trigger btn right-align"
   href="#modal1">inscription</a>
Et la modale correspondante:
<div id="modal1" class="modal">
    <div class="modal-content">


    </div>
    <div class="modal-footer">

    </div>
</div>
Quand on clique sur le bouton d’inscription, on appelle ce script javascript:
$(document).ready(function() {
//On écoute le "click" sur le bouton ayant la classe "modal-trigger"
$('.modal-trigger').click(function () {
//On initialise les modales materialize
        $('.modal').modal();
        //On récupère l'url depuis la propriété "Data-target" de la balise html a
        url = $(this).attr('data-target');
        //on fait un appel ajax vers l'action symfony qui nous renvoie la vue
        $.get(url, function (data) {
            //on injecte le html dans la modale
            $('.modal-content').html(data);
            //on ouvre la modale
            $('#modal1').modal('open');
        });
    })
});
Le contrôleur est donc appelé par un appel ajax. C'est la même action qui va servir à afficher le formulaire ou à traiter la soumission. Voici l’action du contrôleur:
/**
 * @Method({"GET", "POST"})
 * @Route("/competition/{id}/inscription", name="competition-inscription")
 * @param Request $request
 */
public function inscriptionAction(Competition $competition, Request $request)
{
    $inscrit = new Inscrit();
    $form = $this->createForm(InscritType::class, $inscrit);
    $form->handleRequest($request);
    if ($form->isSubmitted() && $form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $inscrit->setDateInscription(new \DateTime());
        $inscrit->setCompetition($competition);

        $em->persist($inscrit);
        $em->flush();
        $request->getSession()->getFlashbag()->add('success', 'Votre inscription a été enregistré.');
        return $this->redirectToRoute('competitions');
    }
    return $this->render(
        //On affiche  une vue twig simple (pas de head ni rien, donc aucun héritage de template...) qui sera intégrée dans la modale.
        'competitions/competitionModale.html.twig', array('form' => $form->createView(), 'competition' => $competition
        )
    );
}
La vue twig est une vue très simple qui ne doit hériter de rien:
{{ competition.titre }}
    <!-- Il faut préciser l'action dans le formulaire -->
    {{ form_start(form, {'action': path('competition-inscription', { 'id': competition.id })}) }}
    {{ form_widget(form) }}
    {{ form_end(form) }}
Conclusion
Comme vous le voyez, il n'y a rien de très compliqué, l'important est de bien comprendre le principe d'appel ajax pour afficher le formulaire à l'intérieur de la modale. Cette action peu être un peu longue, je vous conseille d'utiliser une icône de chargement, d'assombrir la page etc... vous trouverez plein de ressources sur le web pour ça.

0 thoughts on “Insérer un formulaire dans une modale avec Symfony et MaterializeCSS

  • Merci pour ce tuto.
    Un petite precision : en cas d’erreur de saisie du formulaire, comment fait on pour rediriger vers la page de base et rouvrir le modal ?
    Dans l’état des choses, competitionModale.html.twig s’affiche toute seule sans s’intégrer dans la page.

    • Si le formulaire n’est pas valide, $form->isValid() va renvoyer « false ». Tu peux donc ajouter une condition dans l’action du contrôleur pour le gérer

      • Sylvain says:

        Pardon, jai mal posé ma question.
        Dans le cas ou le bouton d’inscription est dans la barre de navigation, donc présent sur toutes les pages… comme le contrôleur est lancé par ajax, le referer ne dit pas a partir de quelle page on clique sur le bouton.
        Que je mette dans ma conditions isvalid un render(referer) ou que je laisse comme tel, le formulaire réapparaît sur une page totalement vierge n’incluant logiquement pas le layout.

        Existe t il une solution pour passer au controleur le nom de la page qui lance l’action ajax… et, si isvalid est à false, faire en sorte depuis ce même contrôleur de retourner à la page puis relancer une action modal-trigger ?

        J’ai bidouillé une solution avec des variable de session indiquant la derniere pas consultée … mais ça n’est franchement pas du tout propre comme alternative.

  • Sylvain says:

    Merci beaucoup pour ton blog et tes réponses.
    L’utilisation des modales est vraiment élégante et pratique du point de vu utilisateur… mais complexifie beaucoup la programmation. C’est sans doute pour cela que l’on n’en voit pas dans les sites les plus connus.

    Pour nous autres débutants ou amateurs, c’est toujours intéressant à utiliser pour apprendre, mais il faut bien garder en tête que ça a tendance à rajouter beaucoup d’heures et de lignes de code au projet de site.

    Qu’en penses-tu ?

    • Oui, effectivement, j’ai eu a les utiliser pour deux projets et j’avoue que j’ai mis pas mal de temps à comprendre (je suis débutant sur Symfony). C’est d’ailleurs pour cette raison que j’ai fait cet article.

Leave a Reply

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.