Afin d’aller encore plus loin, on va voir comment insérer des blocs dans nos blocs grâce au composant InnerBlocks. Et vous verrez que c’est hyper facile. On va donc pouvoir créer des blocs structurels, et choisir quels blocs pourront être utilisés à l’intérieur.
Sommaire du cours
Lorsque vous utilisez le bloc groupe, bannière ou encore colonne de WordPress, vous pouvez insérer à l’intérieur d’autres blocs. On obtient alors des blocs imbriqués les uns dans les autres :
On peut très observer cette indentation grâce à la vue en liste, à gauche.
Dans ce cours, nous allons voir comment mettre en place un bloc conteneur qui acceptera des blocs enfants, et on verra notamment comment limiter le choix de ceux qui pourront être insérés.
Créer un conteneur de blocs avec InnerBlocks
Pour commencer, on va créer un bloc conteneur tout simple grâce au composant <InnerBlocks /> de WordPress et vous allez voir comme c’est simple de l’utiliser.
Pour ceux qui ont la version premium de la formation, vous trouverez le code du bloc dans le dossier /src/08-innerblocks/.
Le composant InnerBlocks
Pour déclarer un composant acceptant des bloc enfants, rien de plus simple donc.
Vidéo premium
Cette vidéo est réservée aux détenteurs de l’offre premium.
Envie de nous rejoindre ?
Voici le code minimum à écrire pour cela :
Et c’est tout ! On a simplement besoin d’appeler le composant InnerBlocks à l’endroit où on souhaite ajouter la possibilité d’insérer des blocs.
Ce composant est importé au début du fichier, au même titre que useBlockProps, à partir de la librairie @wordpress/block-editor.
Pour nous rendre compte du résultat, j’ai ajouté un liseret coloré autour du conteneur ainsi qu’une marge interne à partir du CSS :
Lorsque vous insérez ce bloc dans le contenu d’une publication, vous allez pouvoir insérer à l’intérieur d’autres blocs, grâce au bouton + qui apparait en bas à droite lorsque celui-ci est sélectionné dans l’éditeur :
Du côte du save.js, pour l’enregistrement, c’est pas bien plus compliqué non plus.
Cette fois, on utilise InnerBlocks.Content, de la même manière que RichText.Content, afin de permettre à WordPress de préparer et traiter le contenu à afficher et le convertir en HTML prêt à l’enregistrement.
Comme vous l’avez peut-être remarqué, on n’a même pas besoin de définir d’attributs pour ce bloc, Gutenberg s’occupe de tout.
Et si on jette un œil au HTML généré par l’éditeur, c’est ultra simple :
C’est tout pour les bases ! Qui aurait cru que ça allait être aussi simple de pouvoir insérer des blocs enfants dans notre bloc custom ?
Avec ça, libre à vous de faire des blocs plus évolués, des éléments de structures comme des sections, colonnes… Avec les blocs imbriqués, vous n’avez plus de limites !
Limiter les blocs autorisés
On va maintenant pousser la configuration un peu plus loin grâce à quelques réglages de ce composant.
Vidéo premium
Cette vidéo est réservée aux détenteurs de l’offre premium.
Envie de nous rejoindre ?
Et le premier que je veux vous montrer va nous permettre de limiter les blocs autorisés à l’intérieur de notre conteneur.
Ici, j’ai simplement défini les blocs autorisés dans une constante ALLOWED_BLOCKS avant le return(). Pour cela j’ai utilisé les noms internes des blocs, comme core/image.
Vous pouvez connaître la liste complète des blocs et leurs noms ici :
Bien sûr, ça fonctionne aussi avec vos blocs custom et ceux fournis par les extensions. Pour cela, utilisez le nom que vous avez indiqué dans la propriété name du block.json.
Du côté de l’éditeur, lorsqu’on clique sur le bouton +, seuls les blocs définis sont disponibles :
Cette option est super pratique pour garder le contrôle sur ce que pourront faire vos utilisateurs avec leurs contenus.
Définir un modèle type
Maintenant, on va voir comment préparer un contenu type qui sera automatiquement inséré avec notre conteneur.
Vidéo premium
Cette vidéo est réservée aux détenteurs de l’offre premium.
Envie de nous rejoindre ?
On va voir qu’on peut même verrouiller le template créé et n’autoriser que la modification des contenus.
Cette fois, on ajoute la propriété template dans InnerBlocks qui me permet de définir le template par défaut à afficher grâce à la constante BASE_TEMPLATE et qui est un tableau (= une liste d’éléments).
À l’intérieur, j’ai d’autres listes dans lesquelles j’indique à chaque fois en premier le nom du bloc à afficher, et ensuite j’enchaîne avec un objet qui va contenir les attributs de chaque bloc.
Dans cet exemple, j’insère d’abord une image vide (qui sera affichée en gris), puis ensuite un titre dans lequel j’indique en placeholder « Your title here » puis un paragraphe.
Reportez-vous à la liste des blocs dans la documentation pour connaître les noms des blocs mais aussi la liste des attributs disponibles.
Voici le résultat :
De là, vous n’avez plus qu’à définir un contenu pour chaque bloc et sélectionner une image.
Gérer des éléments imbriqués dans votre template
Vous pourrez également imbriquer plusieurs niveaux de blocs grâce aux groupes et aux colonnes.
Vidéo premium
Cette vidéo est réservée aux détenteurs de l’offre premium.
Envie de nous rejoindre ?
En utilisant un bloc conteneur (groupe, colonnes, bannière…), utilisez le troisième argument. Celui-ci vous permettra d’indiquer quels blocs insérer à l’intérieur.
Exemple avec des colonnes :
Faites très attention aux crochets, car comme vous pouvez le voir dans l’exemple ci-dessus, il y en a beaucoup qui s’imbriquent ensemble, et ce n’est pas très facile à lire où à manipuler !
Cela dit, ça permettrait de réaliser des templates avec de belles structures complexes pour vos blocs conteneurs.
Verrouiller le modèle
Si vous voulez forcer vos utilisateurs à respecter le modèle, vous pouvez le verrouiller contre le déplacement et la suppression très facilement. Ainsi, ils pourront uniquement éditer le contenu.
Vidéo premium
Cette vidéo est réservée aux détenteurs de l’offre premium.
Envie de nous rejoindre ?
Pour cela, ajoutez simplement templatelock dans votre code, avec la valeur all :
Désormais, on ne peut plus supprimer les blocs enfants, ni les déplacer, ni en insérer d’autres. On voit d’ailleurs un cadenas dans la vue en liste :
Comme l’indique la documentation de WordPress, il existe d’autres valeurs pour templateLock :
'insert': impossible d’insérer un nouveau bloc mais on peut déplacer ceux existants ;'all': impossible de supprimer, déplacer ou ajouter un bloc ;{false}: pas de verrouillage appliqué ;'contentOnly': supprime toutes les options de la toolbar du bloc comme « copier les styles », « verrouiller », « copier / coller… ».
Afficher un exemple du bloc avec des enfants
Dans les autres blocs, on définissait des valeurs dans example du fichier block.json afin de générer un aperçu sympa du bloc dans le menu d’insertion des blocs. On va pouvoir en faire de même avec notre conteneur.
Vidéo premium
Cette vidéo est réservée aux détenteurs de l’offre premium.
Envie de nous rejoindre ?
Pour cela, on va cette fois remplir la sous-section innerBlocks de example, au lieu de attributes avec la même structure que pour le template par défaut :
Et dans l’éditeur, on aura cet aperçu :
Changer l’élément HTML avec useInnerBlocks
Enfin, il existe une méthode alternative à InnerBlocks pour afficher les blocs enfants, qui vous permettra de maîtriser le HTML généré.
Vidéo premium
Cette vidéo est réservée aux détenteurs de l’offre premium.
Envie de nous rejoindre ?
Imaginons un exemple plus complexe où vous souhaitez insérer vos blocs enfants dans une div qui porte la classe children :
Vous pouvez à la place utiliser la fonction useInnerBlockProps() (à importer également depuis @wordpress/block-editor) et faire d’une pierre 2 coups :
D’ailleurs, pour en revenir à notre premier exemple, on aurait pu récupérer les blockProps dans les InnerBlockProps et simplifier au maximum :
Les approches ne changent rien au fonctionnement, à part simplifier la syntaxe de votre code, donc faite selon ce qui vous semble le plus logique !
Si vous voulez encore plus d’exemples, consultez la documentation WordPress dédiée aux nested blocks.
Pas mal non ? Pour finir avec des bases, j’aimerai laisser la parole à Florian Truchot, véritable pionner du FSE, qui utilise intensivement Gutenberg et les blocs dans ses projets depuis maintenant de nombreuses années :
Le conseil de Florian Truchot
Développeur & Formateur WordPress
Depuis l’apparition des blocs imbriqués, je les utilise dans quasiment tous mes blocs, en remplacement du composant RichText. De cette manière, j’offre la possibilité à mes clients d’insérer du texte riche même à l’intérieur de nos blocs maison.
Grâce à l’API développeurs de Gutenberg, on a pu réussir à mettre cela en place pour tous nos projets. C’est aujourd’hui un énorme gain de temps pour nous, et une satisfaction client sans précédent.
Un bloc répéteur avec un seul type d’enfant
Avant de clôturer ce cours, je vais vous montrer un exemple dans lequel on va mettre en pratique ce que l’on a vu précédemment avec <InnerBlocks />, dans le but de faire un bloc de type « répéteur » un peu comme on en a l’habitude avec ACF, mais à la mode Gutenberg.
Du RichText multiligne aux blocs parents/enfants
Dans les tous premiers temps de Gutenberg, le composant RichText possédait une propriété multiline qui permettait de créer plusieurs paragraphes, éléments de liste à partir du même bloc. Mais il a fini par être déprécié.
Vidéo premium
Cette vidéo est réservée aux détenteurs de l’offre premium.
Envie de nous rejoindre ?
Et pour cause, Gutenberg allait unifier les façons de faire : dorénavant, on privilégiera l’utilisation des blocs parents et les blocs enfants.
C’est le cas de la liste à puces, si vous regardez bien :
Chaque élément de liste est un bloc enfant du bloc « Liste ». L’avantage, c’est que chaque élément de liste pourra avoir un réglage différent des autres. Par exemple, un élément en particulier pourra avoir une couleur différente des autres.
Bien entendu, vous ne pouvez pas utiliser le bloc « Élément de liste » en dehors du bloc « Liste ».
Et lorsqu’on est dans la liste, on peut insérer uniquement des éléments de liste. Au final ce concept c’est un peu le principe des répéteurs ACF, mais en version Gutenberg !
Créer son propre bloc répéteur avec Gutenberg
On va justement voir comment faire la même chose avec un bloc sur-mesure qui présente une todo list.
Vidéo premium
Cette vidéo est réservée aux détenteurs de l’offre premium.
Envie de nous rejoindre ?
Pour ceux qui suivent la formule premium de la formation, vous trouverez le code de cet exemple dans le dossier /src/09 repeater/ pour le parent et /src/09 item/ pour l’enfant.
Voici à quoi ressemble les deux bloc en action :
Le bloc parent
Commençons par le bloc parent et plus précisément par le edit.js. Ici, rien de nouveau, à part qu’on va n’autoriser qu’un seul enfant dans ALLOWED_BLOCKS, notre bloc capitainewp/item.
À partir du moment où l’on autorise qu’un seul bloc, Gutenberg va arrêter de nous proposer la fenêtre de suggestion de blocs. Lorsqu’on va cliquer sur le bouton +, le seul bloc enfant possible sera ajouté automatiquement.
Le bloc enfant
Maintenant passons au fichier block.json du bloc enfant. Afin de déclarer qu’il est forcément un bloc enfant d’un autre bloc, c’est dans la propriété parent que ça va se passer :
La propriété parent est un tableau dans lequel on peut mettre plusieurs parents si besoin, mais en général, on n’en définit qu’un seul. Malgré tout, on doit toujours mettre les crochets […] désignant un tableau.
Bon, dernier problème ! Lorsqu’on appuie sur la touche « Entrée » sur un élément, on a un retour à la ligne à la place de créer un nouveau bloc.
C’est le fonctionnement normal du RichText mais pour le coup, il ne nous arrange pas. Ne vous inquiétez pas, on va solutionner ça dans le prochain cours sur les données et la fonction useSelect.
La possibilité d’imbriquer des blocs est très intéressante et devrait vous ouvrir de nombreuses portes. Avec ça, vous vous ouvrez encore à d’autres horizons avec les blocs sur-mesure.
Dans le prochain cours, on va aborder un concept très important de WordPress et de l’éditeur : les hooks React useSelect et useDispatch, qui vont nous permettre de récupérer des données de l’éditeur et du site, mais également de modifier à distance d’autres blocs.
GINESTE Bernard
Le 23 août 2023
Bonjour,
Cet article est très intéressant. Mais je voudrais insérer plusieurs InnerBlocks dans un bloc. Pour cela j’ai dupliqué les séquences d’insertion dans edit.js et save.js
Le problème, c’est que, lorsqu’on insère un block dans un des InnerBlocks, cela se répercute sur tous les autres.
Connaissez vous la raison de ce comportement et le moyen d’y remédier ?
Merci d’avance.
Maxime BJ
Le 23 août 2023
Il est impossible d’avoir plusieurs InnerBlocks, c’est pour cela ! Ce n’est pas une limitation de WordPress, c’est le fonctionnement de React qui est en cause ici. Il faut alors que tu penses tes blocs autrement du coup. Comme par exemple ajouter un autre niveau de blocs (qui seraient répétables et qui auraient chacun leurs enfants).
gehin nicolas
Le 29 janvier 2025
Bonjour, la solution pour résoudre cette limitation est de créer un bloc avec uniquement un seul `InnerBlocks` (par exemple, `mon-slug/inner-block`), ensuite on peut insérer ce block autant de fois qu’on le souhaite dans le **template** du block parent
GINESTE Bernard
Le 24 août 2023
Merci beaucoup pour cette réponse.
Du coup, j’ai remarqué que InnerBlocks est au pluriel, ce qui laisse entendre que ce « réceptacle » »peut contenir plusieurs blocs.
Aussi, j’ai tenté ceci :
après avoir défini un premier bloc dans l’InnerBlocks, j’ai déployé le menu de ce premier bloc et j’ai pu choisir ‘ajouter avant’ ou ‘ajouter après’ pour insérer un nouveau bloc, et ainsi de suite.
C’était ce que je voulais faire et ça fonctionne !
Je profite de cette réponse pour vous féliciter de la clarté de vos exposés, qui permettent vraiment de s’initier à la réalisation des blocs personnalisés, sans être bloqué par des insuffisances d’information.
Et en plus vous répondez aux questions qu’on vous soumet !
Bien cordialement
Gaëtan
Le 20 septembre 2023
Bonjour,
J’ai une question concernant la partie $template :
Dans le cas où on veut insérer un bloc acf custom dans cette variable $template, comment peut-on récupérer les champs acf de ce bloc ?
Ex : j’ai un bloc acf appelé par exemple ‘testimonial’, comprenant 2 acf fields ‘citation’ et ‘auteur’.
Je veux inclure ce bloc dans $template, et mettre une citation et un auteur par défaut.
Je pensais écrire comme ça :
[ ‘acf/testimonial’, { citation: ‘Hello !’, auteur: ‘Jean-Michel’ } ],
Mais ça ne fonctionne pas… Tu crois que c’est possible de le faire ?
merci pour ta réponse
Maxime BJ
Le 20 septembre 2023
Ah très bonne question ! Malheureusement je n’ai pas la réponse. C’est super mal documenté côté WP déjà ça. Mais en tous cas j’aurais fait comme tu as dit, c’est ce qui m’aurait semblé le plus judicieux. Il faut bien que citation et auteur soient les « slugs » de tes champs ACF mais je pense que tu as bien vérifié que c’était le cas. Si tu trouves la solution, je suis preneur !
Gaëtan
Le 21 septembre 2023
La réponse ici >> https://twitter.com/BillErickson/status/1704862320751472931
Ça fonctionne, c’est cool !
Maxime BJ
Le 22 septembre 2023
Ok ! Il fallait viser l’identifiant du champ, et non pas son nom directement ! Bien vu !