Formation « Créer des blocs avec Gutenberg »

Hooks Gutenberg : ajouter des paramètres à un bloc existant

Lecture : 6 minutes • 0

Tout comme avec PHP, il est possible d’utiliser des hooks WordPress en JS afin de modifier le comportement de blocs existants. Ça peut être très pratique pour améliorer un bloc natif par exemple, sans avoir à le refaire.

Dans ce cours, on va voir comment tirer parti des hooks JS de Gutenberg, afin de modifier le comportement de blocs existants.

Hooks

Définition

Les Hooks sont des fonctions déclarées par le développeur de thème ou d’extension qui permettent d’interagir avec le coeur de WordPress, d’autres thèmes ou extensions et lancés à des moments clés de leur exécution. Par exemple, on peut intercepter le moment où WordPress enregistre un article dans la base, afin d’y apporter des modifications. Il existe 2 types de Hooks : les actions, un moment clé pour lancer ses propres fonctions, et les filtres, pour intercepter une valeur à un moment donné et la modifier.

Traduction : Crochets

Le fonctionnement est un peu le même que pour les Hooks en PHP, qu’on a pu aborder dans la formation développeur de thème, mais la syntaxe à l’intérieur sera un peu différente, à cause de la nature même de React.

Mais vous allez voir, ce n’est pas très compliqué une fois qu’on a compris le principe !

Objectif : ajouter des paramètres à un bloc existant

Dans ce cours, je vais vous montrer comment modifier le comportement d’un bloc existant sans modifier directement son code source. Le but étant de lui ajouter de nouveaux paramètres qui n’étaient pas présents nativement.

Pour cela, j’ai déclaré un bloc 17-hooks dans le plugin d’exemple qui va nous permettre de nous exercer.

C’est ce bloc que l’on va hooker. Bon, c’est un peu bête car on a accès au code et on pourrait le modifier à volonté : mais on va tout de même utiliser les hooks pour comprendre le principe.

De là, vous pourrez hooker n’importer quel bloc existant, qu’il soit issu du coeur de WordPress ou d’une autre extension.

Conseil

Les hooks vont permettre de modifier un bloc du coeur ou d’une autre extension, dont le code original ne nous est pas accessible.

Notre bloc est tout simple : il ne propose aucune option particulière, un peu comme les tous premiers blocs de la formation.

Ce que l’on aimerait maintenant, c’est ajouter une option dans l’inspecteur pour changer la taille du texte dans le bloc : petit, moyen, ou grand.

le bloc possède un paramètre de taille qui n'est pas présent par défaut
Le champ de taille du texte a été ajouté via un hook

Pour en arriver là, on va devoir faire 4 actions. Il faut :

  1. D’abord ajouter un nouvel attribut size pour sauvegarder notre option ;
  2. Ensuite insérer notre champ select dans l’inspecteur ;
  3. Ajouter la classe CSS (petit, moyen, grand) à notre bloc dans l’éditeur ;
  4. Ajouter la classe CSS au HTML enregistré du bloc pour le front.

Ces 4 actions vont s’effectuer via 4 hooks (filtres) différents, fournis par WordPress.

On va maintenant se rendre dans le fichier hooks.js pour voir comment fonctionnent nos hooks.

Déclarer les hooks

Pour déclarer les hooks, on va faire appel à la fonction addFilter() fournie par WordPress.

JSX
17-hooks/hooks.js

Il faut bien penser en premier lieu à importer la librairie addFilter de WordPress, en haut du fichier.

Ensuite, la fonction addFilter() possède 3 arguments. Le premier est le nom du hook sur lequel on veut se brancher.

  1. blocks.registerBlockType se branche sur la définition du bloc, et nous permet d’accéder aux attributs de celui-ci.
  2. editor.BlockEdit se branche au code du bloc pendant l’édition, et nous permet d’ajouter nos propres champs de paramètres dans l’inspecteur.
  3. editor.BlockListBlock se branche au moment du rendu du bloc dans l’éditeur, et nous permet d’ajouter la classe CSS custom dans l’éditeur.
  4. blocks.getSaveContent.extraProps se branche au moment de l’enregistrement du bloc en HTML et nous permet d’ajouter notre classe CSS pour le front.

Le second paramètre de la fonction permet de nommer notre hook. On va lui donner un nom arbitraire, mais unique, afin de ne pas faire conflit avec d’autres éventuels hooks présents sur ces actions.

Enfin, le troisième argument est la fonction de callback, c’est à dire la fonction que WordPress doit appeler lorsqu’il atteint l’action concernée.

On va maintenant étudier chacune de ces fonctions en détails.

Hook #1 : Ajout d’un nouvel attribut dans le bloc

Comme en PHP, ces hooks sont appelés dès que WordPress déclenche l’action. Cela veut dire que notre fonction va se lancer pour chaque bloc de l’éditeur. Mais ce n’est pas ce que l’on veut. On veut exécuter ce hook uniquement pour un bloc bien précis.

La première chose à faire va donc être de vérifier qu’on est bien dans le bon bloc.

JSX
17-hooks/hooks.js

Au début du fichier, on va déclarer une constante allowedBlocks dans laquelle on va définir le ou les blocs concernés par nos hooks. Ici, j’ai simplement ciblé mon bloc, mais on aurait pu très bien ajouter d’autres blocs, comme par exemple :

JSX
17-hooks/hooks.js

Astuce

Pour connaitre le nom exact des blocs, passez en mode « éditeur de code » dans l’éditeur via le menu 3 points en haut à droite, afin de consulter le HTML. Les blocs natifs s’appellent tous core/<nom>.

Si vous avez suivi la formation « Développeur de thèmes », vous vous souvenez probablement que lorsqu’on utilisait le hook save_post, on vérifiait avant toute chose que l’on était bien dans le bon type de publication avant de continuer.

Eh bien là, c’est la même chose : au début de notre fonction, on va vérifier qu’on est bien dans le bon bloc grâce à la méthode includes(). Le nom du bloc est automatiquement fourni en second paramètre du hook WordPress : name.

JSX
17-hooks/hooks.js

Information

La fonction includes() en JS est un peu l’équivalent du in_array() de PHP.

Ensuite c’est tout simple : si on est dans le bon bloc, alors on va insérer dans settings.attributes (l’objet qui contient tous les attributs du bloc) notre nouvelle donnée à enregistrer : size.

Pour rappel, les attributs sont les données personnalisables d’un bloc, que l’on déclare généralement dans block.json.

JSON
4-richtext/block.json

On vient donc ajouter notre attribut size aux attributs déclarés initialement par le bloc, sans modifier le code source original du bloc. C’est là toute la puissance des hooks !

Hook #2 : Ajout des champs dans l’inspecteur du bloc

Maintenant qu’on a notre nouvel attribut, il va falloir injecter notre champ select dans l’inspecteur du bloc, afin de pouvoir donner à l’utilisateur la possibilité de changer la valeur. Voici le code du hook. Celui-ci est un peu plus conséquent :

JSX
17-hooks/hooks.js

Tout d’abord, on peut voir l’usage de la fonction createHigherOrderComponent(), qui permet de surcharger un composant React existant.

En d’autres termes : on prend un composant (notre bloc) et on lui ajoute d’autres éléments (notre champ select).

C’est en réalité une technique propre à React, qui s’appelle High Order Component (ou HOC).

Le bloc qu’on s’apprête à surcharger sera appelé Block dans la fonction, il est passé en premier paramètre du HOC.

La première chose que l’on va faire, là encore, c’est tout d’abord vérifier qu’on est bien dans le bon bloc, via :

JSX

Cette fois, le nom du bloc est récupéré dans les props (via props.name). Si on n’est pas dans le bon bloc, alors on retourne simplement le bloc original non modifié : dans ce cas, notre HOC ne sert à rien.

Mais si on est dans le bon bloc, alors on va pouvoir ajouter notre champ à l’inspecteur. Regardons le contenu du return():

JSX

On observe tout d’abord qu’on retourne notre composant original, nommé BlockEdit dans le HOC, puis on ajoute à l’inspecteur, via <InspectorControls>.

Le SelectControl propose les 3 options : petit, moyen et grand, et va s’occuper de l’enregistrement de l’attribut via la fonction onChange.

JSX

Désormais, lorsqu’on sélectionnera le bloc dans l’éditeur, on devrait désormais voir notre champ select dans l’inspecteur à droite !

Hook #3 : Ajout de la classe dans le bloc dans l’éditeur

Ce troisième hook va permettre d’agir sur le bloc lorsqu’il est rendu dans l’éditeur. On va utiliser là aussi un HOC afin de pouvoir injecter notre classe sur mesure.

La première chose qu’on va faire, c’est vérifier qu’on est dans le bon bloc. C’est toujours le même code, et vous l’avez compris, mais cette vérification est nécessaire dans chaque hook.

JSX
17-hooks/hooks.js

Si on est dans le bon bloc, on va ajouter une classe et renvoyer le bloc. Pour cela on ajoutera la propriété className dans notre Block original. Le nom de classe va se baser sur notre valeur size. On pourra alors avoir :

  • has-size-small
  • has-size-medium qui est la valeur par défaut
  • has-size-large

On va donc définir ces classes dans le fichier CSS de notre bloc :

Sass
17-blocs/style.scss

Maintenant, dès qu’on va changer la valeur de notre champ select, le bloc se mettra à jour pour afficher la classe correspondante, par exemple has-size-large. Dans ce cas, on devrait voir que le texte est affiché en plus gros.

Hook #4 : Ajout de la classe dans le HTML sauvegardé

Et pour finir, il faut ajouter notre classe lors de l’enregistrement HTML de notre bloc, afin qu’elle soit affichée sur le site, en front.

JSX
17-hooks/hooks.js

Ici c’est tout simple : on récupère notre attribut size, et on génère notre nom de classe CSS.

Et voilà, tout est enfin prêt ! Notre bloc est désormais amélioré grâce aux 4 hooks. Vous avez désormais le principe général des hooks.

Découvrir d’autres filtres

On a vu 4 filtres dans ce cours, mais il en existe pas mal d’autres. Certains concernent l’éditeur et d’autres directement les blocs.

Pour les découvrir, je vous invite à aller faire un tour dans la documentation officielle de WordPress. Voici les hooks qui concernent l’éditeur :

Les hooks de l’éditeur

Et voici les hooks qui concernent plutôt les blocs :

Les hooks des blocs


C’était une première approche des hooks de Gutenberg. Maintenant que vous connaissez le principe, vous allez pouvoir modifier en profondeur le fonctionnement des blocs et de l’éditeur, directement à partir de votre extension et sans modifier le code original.

0

Questions, réponses et commentaires

Laisser un commentaire