Envoi de formulaire en ajax avec Symfony 4.1

Une problématique qui s’est posée à moi dans un développement récemment était l’envoi d’un formulaire en ajax avec Symfony 4 (fonctionne aussi bien avec Symfony 3).

Contexte

Côté serveur, l’application en question tourne sous Symfony 4.1. En front, pas d’exotisme, j’utilise Twig auquel j’ajoute Bootstrap 4 ainsi que jQuery. Le cas que je vais présenter en exemple est simple : j’affiche une page qui me liste les articles existants, dans cette page, je ferai apparaître une fenêtre modale de création d’article qui contiendra un formulaire qui sera soumis en ajax. Le but est de rester dans la page principale, malgré l’envoi et le traitement du formulaire.

Entité

Une entité relativement basique, nous mettons juste une contrainte d’intégrité sur mes champs pour éviter qu’ils soient vides et ainsi tester que le formulaire est bien validé par Symfony.

Pour la créer :

L’assistant va me demander quels champs nous souhaitons créer, nous allons créer simplement un champ title (tous les paramètres par défaut) et un champ text (il suffit juste de préciser le type text, tous les autres paramètres également par défaut).

 

Formulaire

Pour le formulaire, idem, que du basique, j’utilise la commande console pour gagner du temps.

La commande va me demander l’entité associée, nous précisons donc Article.

Nous allons légèrement modifier le code généré afin de retirer le caractère obligatoire des champs en HTML5. Attention, ce n’est pas à faire en temps normal, mais de cette façon, nous allons pouvoir nous assurer que le formulaire est bien géré et validé correctement en ajax un peu plus bas.

Controller

Concernant le controller, comme d’hab, nous  le générons avec la console :

La commande me génère donc notre controller avec une action index, ainsi qu’un template article/index.html.twig.

Nous allons modifier l’action par défaut afin de récupérer la liste des articles existants.

Nous allons également créer une action pour la création de notre article, elle est très similaire à ce que vous pouvez connaître dans un CRUD classique avec Symfony, si ce n’est qu’au lieu de rediriger vers une autre action après l’enregistrement, on renvoie simplement une réponse qui va indiquer que l’enregistrement a été effectué. Il y a différentes manières de le faire, nous faisons au plus simple en renvoyant simplement un objet Response() qui contiendra le message « success ».

En annotation, vous remarquerez également le paramètre condition= »request.isXmlHttpRequest() » qui permet de limiter les appels à cette action aux seuls appels en ajax.

Au niveau du formulaire, nous allons également préciser le paramètre action afin qu’il retourne vers la même action du controller. En effet, comme cette action sera appelée depuis une autre action en ajax, le formulaire renverra vers l’index du controller qui ne sait pas comment gérer le formulaire.

Voici le code :

Templates

Ils sont au nombre de 3, mais seulement 2 vont réellement nous intéresser.

Lors de la génération du controller et de l’action index, un template index.html.twig a été créé, mais également un template base.html.twig dont index.html.twig hérite. Tout cela est réalisé automatiquement par la commande console indiquée plus haut. Nous ne toucherons pas au base.html.twig.

Nous allons d’abord voir le formulaire en lui même. Il nous faut créer un template que nous allons nommer _create.html.twig dans le répertoire templates/article.

Ce template est encore une fois minimaliste, il ne contient que le formulaire de création de l’article.

En revanche, dans index.html.twig, il y a un certain nombre de modification à réaliser. Il faut appeler les différents styles et scripts dont on aura besoin. Il faut également créer la fenêtre modale (grâce à bootstrap) ainsi que le bouton qui sera chargé d’afficher cette modale. Et bien entendu le code javascript où tout va réellement se passer.

Il y a 2 parties à ce code javascript : la première est responsable de l’affichage de la fenêtre modale, et la seconde sera un peu plus chargée, il s’agit de la soumission du formulaire.

Pour la première partie, c’est très classique, un simple appel ajax à l’action article_create de notre controller pour afficher le formulaire dans la fenêtre modale.

Pour la 2ème partie c’est un peu plus compliqué. Je précise que le code présenté ici n’est qu’une proposition, il y a des quantités de manières différentes d’arriver au même résultat. La première chose à faire est de court-circuiter la soumission normale du formulaire afin de la gérer en javascript. Vous remarquerez que l’appel ajax pour la soumission du formulaire est légèrement différent de celui qui a été utilisé pour afficher la fenêtre. En fait je n’utilise pas là directement jQuery, mais un plugin du nom de jQuery form. Il permet de simplifier la soumission en ajax et la serialization des données du formulaire. Je vous invite à y jeter un coup d’oeil parce qu’il est très pratique. Pour être honnête, on aurait pu s’en passer dans cet exemple, il aurait alors fallut serializer les données du formulaire en faisant $form.serialize(). Simple me direz-vous, alors pourquoi ne pas faire ça au lieu de passer par un plugin ? Et bien si vous aviez eu un champ fichier dans votre formulaire, la serialization de ce champ n’aurait pas fonctionné et le champ n’aurait pas été envoyé avec le reste du formulaire.

Je vous invite à regarder plus particulièrement la section success de l’appel ajax. Il y a 2 cas que nous gérons ici, le cas où l’enregistrement s’effectue bien (data == ‘success’) et quand ce n’est pas le cas (et donc que la validation du formulaire ne passe pas). Dans ce 2ème cas de figure, notre controller nous renvoie le formulaire avec ses messages d’erreur. Vous pouvez d’ailleurs faire le test en envoyant le formulaire vide, vous verrez que les messages d’erreurs sont bien affichés.

Voici donc le code de notre template :

Vous avez donc tout ce qu’il faut pour tester notre exemple, une fois que le formulaire aura été validé, la fenêtre va disparaître et le titre de l’article sera affiché dans la liste de la page.

Conclusion

L’envoi de formulaire en ajax avec Symfony n’est pas sorcier une fois qu’on sait comment conjuguer simplement les différents éléments qui doivent entrer en ligne de compte.

Il est également possible de serializer le formulaire avec FormData sur les navigateurs récents, mais l’utilisation du plugin cité un peu plus haut pour cet usage peut rendre la compatibilité de votre code un peu plus large.

Laisser un commentaire

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