Il y a quelques jours, je vous ai expliqué comment intégrer Google Maps dans vos entités Doctrine, maintenant voici comment l’intégrer facilement et proprement dans vos formulaires !
Avant de commencer, je vous conseille de jeter un oeil sur la doc officielle concernant les formulaires virtuels.
De quoi avons nous besoin ?
Pour intégrer Google Maps dans nos formulaires, nous allons utiliser le plugin jQuery Address Picker. Ce plugin nous permet en tapant simplement l’adresse souhaitée de récupérer les informations suivantes :
- Locality (La ville)
- Country (Le pays)
- Lat (La latitude)
- Lng (La longitude)
Pour tester votre code, faites une entité de la même forme que dans cet article.
Le formulaire virtual
Bien ! Maintenant que nous savons ce qu’il nous faut, nous allons créer notre FormType de type virtual que nous allons appeler gmap_address :
<?php namespace My\UtilsBundle\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormBuilderInterface; /** * GMapAddressType * * @author Sullivan SENECHAL */ class GMapAddressType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('address', null, array( 'required' => true, )) ->add('locality', 'hidden', array( 'required' => false, )) ->add('country', 'hidden', array( 'required' => false )) ->add('lat', 'hidden', array( 'required' => false )) ->add('lng', 'hidden', array( 'required' => false )) ; } public function getDefaultOptions(array $options) { return array( 'virtual' => true, // Ici nous précisons que notre FormType est un champ virtuel ); } public function getName() { return 'gmap_address'; // Le nom de notre champ, il sera utilisé après } } ?>
Vous remarquez que tout les champs sauf ‘address’ sont cachés, c’est tout simplement pour faire un formulaire simple avec le champ éditable de l’adresse et la carte juste en dessous, vous pouvez bien sur les changer ! 😉
Le template twig
Créer un champ virtuel n’est pas tout, notre formulaire sera un peu spécial vu qu’il intégrera une carte Google Maps. Il faut donc le préciser en créant un template comme suit :
{# src/My/UtilsBundle/Resources/views/Form/fields.html.twig #} {% block gmap_address_widget %} <div id="{{ id }}_gmap_address_widget"></div> <div id="{{ id }}_input">{{ block('form_widget') }}</div> <div id="{{ id }}_map" class="gmap_address_map"></div> <script type="text/javascript"> $(function() { var addresspickerMap = $("#{{ form.address.get("id") }}").addresspicker({ regionBias: "fr", elements: { map: "#{{ id }}_map", locality: '#{{ form.locality.get("id") }}', country: '#{{ form.country.get("id") }}', lat: "#{{ form.lat.get("id") }}", lng: "#{{ form.lng.get("id") }}" } }); var gmarker = addresspickerMap.addresspicker("marker"); gmarker.setVisible(true); addresspickerMap.addresspicker("updatePosition"); }); </script> {% endblock %}
Votre block doit s’appeler gmap_address_widget afin d’être utilisé par votre FormType gmap_address.
Ce template se sépare en deux parties, le code html où sont générés nos champs de formulaire avec un div pour la carte gmap ainsi qu’un code javascript pour activer le plugin jQuery Address Picker sur le champ d’adresse (voir la démo sur github).
Ici on se sert de la variable id, générée lors de la création de vos formulaires, on peut aussi récupérer les ids de chaques field, comme ici ou ils sont passés en paramètre dans les configurations du plugin.
Je ne me suis pas attardé sur la personalisation des champs en utilisant juste form_widget, ce qui nous donne déjà un très bon résultat, libre à vous de le changer ! 🙂
N’oubliez pas d’ajouter votre template dans votre fichier config.yml !
twig: debug: %kernel.debug% strict_variables: %kernel.debug% form: resources: - 'MyUtilsBundle:Form:fields.html.twig'
Déclaration en tant que service
Afin d’augmenter la simplicité d’utilisation de votre champ virtual, nous allons le déclarer sous forme de service, voici un exemple en xml :
<?xml version="1.0" ?> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> <parameters> <parameter key="form.type.gmap_address.class">My\UtilsBundle\Form\Type\GMapAddressType</parameter> </parameters> <services> <service id="form.type.gmap_address" class="%form.type.gmap_address.class%"> <tag name="form.type" alias="gmap_address" /> </service> </services> </container>
Ne pas oublier de préciser le tag form.type avec comme alias gmap_address !
Vous pouvez obtenir plus d’informations sur la déclaration d’un Type en tant que service sur cette page.
Intégration dans un formulaire
Voila notre extension de formulaire est prête ! Il n’y a plus qu’à l’utiliser dans notre FormBuilder, pour cela rien de plus simple ! Il suffit simplement de le spécifier de cette facon :
// src/My/MainBundle/Form/Type/PlaceType.php namespace My\MainBundle\Form\Type; use Symfony\Component\Form\FormBuilderInterface; class PlaceType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('address', 'gmap_address', array( 'data_class' => 'My\MainBundle\Entity\Place', )); } }
A noter qu’il faut à chaque fois préciser l’option data_class, nécessaire pour appliquer les données à l’entité concernée. Votre Entity doit donc contenir des attributs identiques à votre FormType.
Importation du plugin dans le layout
Il ne vous reste plus qu’à générer votre formulaire pour voir le résultat, mais avant vous devez ajouter deux choses dans votre layout principal, le plugin javascript et l’api google map, ajoutez-les dans les balises <head> :
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script> <script type="text/javascript" src="/path/to/jquery.ui.addresspicker.js"></script>
Conclusion
C’est normalement tout ce que vous devez savoir, si vous n’avez pas tout compris ou que vous avez une meilleure solution, faites le nous savoir par commentaire ! 😉
Je pense plus tard faire un bundle permettant d’intégrer plusieurs extensions jQuery de ce genre, je vous tiens au courant si ce projet voit le jour, en attendant je vous conseille celui de genemu qui vous propose pas mal d’options ! 😉
Pingback: jQuery Address Picker & Symfony 2 - Cyril Chandelier()