Une Google Map personnalisable dans Gutenberg - Formation Gutenberg - Capitaine WP

Formation « Créer des blocs avec Gutenberg »

Une Google Map personnalisable dans Gutenberg

Lecture :6 minutes •0

Le bloc Google Map que j’ai réalisé est révélateur des bienfaits de Gutenberg : pouvoir éditer sa carte en direct, dans son contenu, sans passer par un shortcode, c’est le rêve ! On va en profiter pour analyser son code dans les moindres détails.

Ce bloc Google Maps permet (ô surprise !) d’afficher une carte Google avec un marqueur, et personnaliser le zoom, la hauteur et même l’apparence :

Le bloc Google Maps en action
Le bloc Google Maps en action

Pour cela j’utilise l’API Google Maps ainsi que l’API Geocoder qui permet de trouver une adresse et la convertir en coordonnées GPS.

Pour fonctionner ce bloc nécessite qu’on lui indique une clé d’API, obtenue auprès de Google et indiquée dans la page Options de mon extension.

Alors la première question que l’on peut se poser, c’est : est-ce que j’aurais besoin d’une libraire Gmap spéciale React ? Je me suis posé cette question, et la réponse est non : la librairie par défaut fonctionnera à merveille (et avec bien plus de facilité que ce que j’avais d’abord imaginé).

Ce serait le cas si vous voulez utiliser une librairie originalement écrite en jQuery, vous trouverez alors sûrement son équivalent React sur le site de NPM.

Analyse du code

En premier lieu, je dois charger la librairie JS Google Map et pour cela je vais utiliser wp_enqueue_script() dans le hook enqueue_block_editor_assets dans classes/Blocks/Gmap.php :

PHP
classes/Blocks/Gmap.php

Je récupère préalablement l’option advanced-gutenberg-blocks-gmap-api-key qui me sera nécessaire au bon fonctionnement de l’API. Si elle n’est pas renseignée, je ne charge pas le script puisque je n’affiche pas la carte, mais une alerte « Veuillez renseigner votre clé d’API ».

Côté admin, cela veut dire que je charge le script Gmap tout le temps, ce qui n’est pas top. J’essaierais d’améliorer ça à l’avenir.

Côté front cependant, je ne charge le script seulement si le bloc est utilisé, et pour cela je le charge directement dans mon template PHP, dans public/templates/gmap.php.

On y aperçoit également le code JS (natif) nécessaire à l’initialisation de la Map, conformément à ce qui est donné dans la documentation officielle.

Les composants JS

On va maintenant aller jeter un oeil aux composants spécifiques de ce bloc, tous situés dans src/blocks/gmap/. On va notamment se pencher sur :

  • <Gmap /> qui représente la carte Google
  • <Geocoder /> qui est le champ qui permet de convertir une adresse postale en coordonnées GPS
  • <StyleSelector /> qui est le champ permettant de choisir le style graphique de la carte

Les deux derniers sont appelés depuis l’inspecteur. Commençons par le Geocoder :

Le Geocoder

La mécanique de ce composant est la même que pour la recherche d’extension / article / produit : un champ permet de lancer la recherche, lié à un Debounce.

Pour lancer une recherche avec le Geocoder Google il suffit d’appeler le code suivant :

JS
src/blocks/gmap/geocoder.js

Je stocke le résultat dans le State du composant. Dans le rendu, je génère une liste d’adresses correspondant aux résultats :

JSX

J’en profite pour tester si c’est bien un tableau, car si ça n’en n’est pas un, c’est que c’est une chaine de caractères, et donc plutôt une erreur à afficher. (Pour rendre ça plus lisible, j’aurais pu stocker une éventuelle erreur dans une hypothétique variable this.state.error plutôt que this.state.results).

Je vais maintenant insister sur un détail important de React qui simplifie grandement la vie.

Au début je me demandais : comment je « stocke » le numéro du résultat pour le retrouver plus tard, dans le genre est-ce que j’affiche l’identifiant dans l’attribut value de mon option, par exemple <option value="12"></option>. En plus là c’est d’autant plus compliqué que l’API Google me renvoie un objet complet, et pas juste une donnée.

En fait il faut bien se rappeler que ce n’est pas au HTML de stocker les données, mais à React. C’est lui qui va donc gérer ça.

Il suffit en réalité de définir dans le onClick la fonction qui va traiter notre donnée (le setAttributes() par exemple) et le résultat en cours, issue de la boucle map() : onClick={ () => this.setGeocodedObj( result ) }.

Ici je lance la fonction setGeocodedObj() qui va jouer l’intermédiaire et extraire la latitude, longitude et l’adresse bien formatée par Google et qui appellera ensuite le setAttributes().

Je n’aurais jamais pu faire ça aussi simplement en jQuery.

Le sélecteur de style

Le sélecteur de style affiche des images montrant les couleurs possibles de la carte.

Le sélecteur de styles

Comme c’est une disposition particulière, il n’existait pas de composant natif pour faire cela, j’ai donc créé le mien.

Avouez que c’est tout de même plus sexy qu’un champ Select.

Les styles sont en fait des tableaux JSON, codifiés par Google. J’ai simplement récupérés ceux montrés en exemple sur la documentation et je les ai stockés dans un fichier à part : src/blocks/gmap/styles.js.

Dans styleSelector j’utilise map() pour parcourir les styles et récupérer l’image correspondante. Ensuite c’est un classique setAttributes() qui enregistre la donnée.

La carte Google Maps

Et enfin, tout se réunit ici. Pour initialiser la carte Google dans ce composant j’utilise simplement le code proposé par la documentation officielle.

  • Pour initialiser la carte, j’utilise new google.maps.Map()
  • Pour initialiser un marqueur, j’utilise google.maps.Marker()
  • Pour initialiser la bulle d’information, j’utilise google.maps.InfoWindow()

Pour faire simple j’ai créé une sous fonction pour chacune de ces tâches, comme ça, lors de l’initialisation du composant dans componentDidMount(), je lance tout ça d’un coup :

JS

Notez que je stocke cela dans une variable gmapObj, qui n’est pas dans le state, car il n’y a pas besoin de réinitialiser les classes Google à chaque rendu du composant.

Lorsqu’il y aura une modification dans les données (par exemple une nouvelle adresse), j’utiliserais componentWillReceiveProps() pour recevoir les nouvelles données et faire la mise à jour du rendu.

Pour cela j’utilise les fonctions fournies par Google :

JS

Pour éviter tout traitement inutile, je vérifie à chaque fois si la nouvelle valeur est différente de la précédente. Cela permet de rester optimal et d’éviter de faire du rendu pour rien.

Au final la seule chose qui lie ma Carte au markup HTML, c’est le document.querySelector(".wp-block-advanced-gutenberg-blocks-gmap__canvas")que j’utilise en premier paramètre de la Google Map.

Au final ce composant utilise simplement le JS fournit par Google Maps, mais en écriture ESnext, et ça fonctionne très bien.

Le problème avec les attributs par défaut

Pour terminer, on va s’attarder sur un problème que vous pourriez rencontrer avec les valeurs d’attributs par défaut.

Dans cette situation, pour que la carte fonctionne je dois initialement lui passer quelques valeurs obligatoires comme les coordonnées, un zoom et une hauteur.

J’indique donc ces valeurs dans les attributs du bloc :

JS
JS src/blocks/gmap/index.js

Cependant il faut savoir que lorsque l’on définit une valeur par défaut dans les attributs, elle n’est pas automatiquement appliquée au code HTML du bloc. Si je passe en mode code editor (Ctrl+shift+alt+M) dans Gutenberg, j’obtiens ceci :

HTML

Au lieu de ceci :

HTML

Côté Gutenberg mes valeurs par défaut existent, ma carte va donc bien s’initialiser. Mais côté PHP, ça va planter.

Il faudra alors donc faire très attention à ce détail à l’avenir : En front il faudra bien penser à définir ces valeurs par défaut car sinon vous aurez des ennuis.

Une solution est de tester les attributs reçus PHP, s’ils n’existent pas, il faut les créer avec une valeur par défaut.

PHP

Du coup si vous venez à changer votre valeur d’attribut par défaut en JS, il faudra bien penser à le changer également en PHP.

L’alternative serait de faire ce test en JS directement, et forcer le setAttributes, mais j’ai eu quelques soucis dans ces cas spécifiques, du coup j’ai préféré le faire en PHP.


J’espère que ces quelques études de cas vous auront appris de nouveaux trucs et vous aident à y voir plus clair pour la réalisation de blocs sur mesure.

Maintenant place au dernier devoir, et dans le prochain chapitre je vous partage des trucs et astuces pratique sur Gutenberg, avec pleins de petites fonctions bien utiles.

0

Questions, réponses et commentaires

Laisser un commentaire