Chapitre 8.6 — InnerBlocks & composition
⏱️ TL;DR —
InnerBlockspermet à votre bloc de contenir d’autres blocs (comme Groupe ou Colonnes). C’est l’équivalent deschildrenen React. On l’utilise dansedit(viauseInnerBlocksProps) et danssave(viaInnerBlocks.Content), et on peut contraindre ce que l’utilisateur y met : blocs autorisés (allowedBlocks), structure de départ (template), verrouillage (templateLock). Pour un bloc dynamique avec enfants, le PHP reçoit le rendu des enfants dans$content.
🎯 Objectifs
- Créer un bloc conteneur avec
InnerBlocks. - Contraindre les enfants (
allowedBlocks,template,templateLock). - Gérer
InnerBlocksen statique (save) et en dynamique ($content). - Comprendre le pont avec les
childrenReact.
1. InnerBlocks = les enfants
Un bloc conteneur laisse l’utilisateur insérer des blocs à l’intérieur. Dans edit, l’approche moderne combine useBlockProps et useInnerBlocksProps :
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
export default function Edit() {
const blockProps = useBlockProps( { className: 'wpr-carte' } );
const innerProps = useInnerBlocksProps( blockProps, {
allowedBlocks: [ 'core/heading', 'core/paragraph', 'core/image' ],
template: [
[ 'core/heading', { level: 3, placeholder: 'Titre…' } ],
[ 'core/paragraph', { placeholder: 'Texte…' } ],
],
} );
return <div { ...innerProps } />; // les enfants se rendent ici
}allowedBlocks: restreint les types de blocs insérables (ex. seulement titre/paragraphe/image).template: la structure de départ (blocs pré-insérés à la création).templateLock:'all'(rien ne bouge),'insert'(pas d’ajout/suppression mais réordonnable),false(libre).
💡 Pour un dev React —
InnerBlocks=props.children.template= les enfants par défaut (comme un composant qui rend des enfants initiaux).allowedBlocks= une contrainte de type sur les enfants (comme validerchildrenpar type).templateLock: 'all'= des enfants figés (composition contrôlée). Vous composez des blocs comme vous composez des composants.
2. Sauvegarde des enfants (statique)
Pour un bloc statique conteneur, save doit rendre InnerBlocks.Content (le HTML des enfants) :
import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';
export default function save() {
const blockProps = useBlockProps.save( { className: 'wpr-carte' } );
return (
<div { ...blockProps }>
<InnerBlocks.Content />
</div>
);
}Le HTML des blocs enfants est sérialisé à l’intérieur du vôtre (imbrication, ch. 3.1).
3. Enfants dans un bloc dynamique
Si votre conteneur est dynamique (rendu PHP, ch. 8.5), le rendu des enfants arrive dans $content :
<?php
// render.php d'un conteneur dynamique
$wrapper = get_block_wrapper_attributes( array( 'class' => 'wpr-carte' ) );
?>
<div <?php echo $wrapper; ?>>
<?php echo $content; // le HTML des InnerBlocks, déjà rendu ?>
</div>$content contient les enfants déjà rendus ; vous les enveloppez. (Ne les ré-échappez pas : ils sont produits par le rendu des blocs enfants.)
4. Contraindre pour livrer une UX propre
Les contraintes servent à guider le créateur (comme pour les motifs, ch. 6.6) :
useInnerBlocksProps( blockProps, {
allowedBlocks: [ 'core/paragraph' ],
template: [ [ 'core/paragraph', {} ] ],
templateLock: 'insert', // l'utilisateur édite le contenu mais ne casse pas la structure
} );- Un bloc « Témoignage » qui n’accepte qu’un
paragraph+ uneimage→ structure cohérente. templateLock: 'all'verrouille totalement (idéal pour un gabarit imposé).
⚠️ Piège —
InnerBlocksen double. Un bloc ne peut avoir qu’un seulInnerBlocks/useInnerBlocksPropspar bloc (une seule zone d’enfants). Pour plusieurs zones (ex. « colonnes »), on crée des blocs enfants dédiés (commecore/columnscontient descore/column), chacun avec sonInnerBlocks. Vouloir deuxInnerBlocksdans un même bloc ne fonctionne pas.
5. Quand utiliser InnerBlocks
- Oui : votre bloc est un conteneur (carte, section, mise en page) dont le contenu doit être composé de blocs (réutilisant paragraphe, image, bouton…).
- Non : votre bloc affiche des données structurées (un livre depuis le catalogue) → pas d’enfants, on rend les champs directement (ch. 8.5, 8.9).
Réutiliser les blocs existants via InnerBlocks (plutôt que recréer des champs) est souvent le bon réflexe : l’utilisateur retrouve des blocs qu’il connaît, avec tous leurs réglages.
✏️ Exercices
- À quel concept React
InnerBlockscorrespond-il ? - Vous créez un bloc « Encadré » qui ne doit contenir qu’un titre et un paragraphe, non supprimables. Quelles options utilisez-vous ?
- Dans un conteneur dynamique, où récupérez-vous le rendu des blocs enfants ?
✅ Solution
- À
props.children:InnerBlocksest la zone où se rendent les blocs enfants (avectemplate= enfants par défaut,allowedBlocks= contrainte de type). allowedBlocks: ['core/heading','core/paragraph'], untemplateavec ces deux blocs, ettemplateLock: 'all'(ou'insert'si on veut permettre l’édition du contenu sans ajout/suppression).- Dans la variable
$contentdurender.php(le HTML desInnerBlocksdéjà rendu), qu’on enveloppe dans le markup du conteneur.
🧠 Quiz de révision
1. Que permet InnerBlocks ?
À un bloc de contenir d’autres blocs (composition), équivalent des children.
2. À quoi sert allowedBlocks ?
À restreindre les types de blocs insérables dans le conteneur.
3. Que fait templateLock: ‘all’ ?
Il verrouille la structure : les enfants ne peuvent être ni ajoutés, ni supprimés, ni déplacés.
4. Comment sauvegarde-t-on les enfants d’un bloc statique ?
Avec <InnerBlocks.Content /> dans la fonction save.
5. Peut-on avoir deux zones InnerBlocks dans un même bloc ?
Non : une seule par bloc. Pour plusieurs zones, on crée des blocs enfants dédiés (façon columns/column).
Chapitre suivant : Les data stores (@wordpress/data).