Chapitre 8.3 — edit, save & attributs
⏱️ TL;DR — Les attributs (déclarés dans
block.json) sont l’état d’un bloc :editles lit viaattributeset les modifie viasetAttributes()(l’équivalent desetState).editrend l’aperçu éditeur ;saveproduit le HTML sérialisé stocké dans le contenu. Les deux enveloppent leur racine avecuseBlockProps()(indispensable). Un attribut peut être sourcé depuis le HTML (source: 'html') pour les blocs statiques. Si le rendu doit varier après coup (données live), on passe en dynamique (ch. 8.5) plutôt quesave.
🎯 Objectifs
- Déclarer et typer des attributs.
- Écrire
edit(lecture viaattributes, écriture viasetAttributes). - Écrire
saveavecuseBlockProps.save(). - Comprendre les attributs sourcés et l’invalidation de bloc.
1. Les attributs = l’état du bloc
Déclarés dans block.json (type + défaut) :
"attributes": {
"titre": { "type": "string", "default": "" },
"afficherPrix": { "type": "boolean", "default": true },
"note": { "type": "number", "default": 0 }
}Dans edit, ils arrivent en props :
export default function Edit( { attributes, setAttributes } ) {
const { titre, afficherPrix, note } = attributes;
// lire : titre ; écrire : setAttributes({ titre: '…' })
}💡 Pour un dev React —
attributes= votre state typé (déclaré dansblock.jsonplutôt qu’unuseState),setAttributes=setState(fusion partielle :setAttributes({ note: 5 })ne touche pas les autres). La persistance est automatique : modifier un attribut met à jour le bloc dans le document, WordPress s’occupe de sérialiser. Vous gérez un composant contrôlé sans écrire la couche de sauvegarde.
2. edit : l’aperçu éditeur
import { useBlockProps, RichText } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
export default function Edit( { attributes, setAttributes } ) {
const { titre } = attributes;
const blockProps = useBlockProps( { className: 'wpr-livre-une' } );
return (
<div { ...blockProps }>
<RichText
tagName="h3"
value={ titre }
onChange={ ( value ) => setAttributes( { titre: value } ) }
placeholder={ __( 'Titre du livre…', 'wpr-books' ) }
/>
</div>
);
}useBlockProps(): obligatoire sur l’élément racine. Il injecte les classes/attributs que l’éditeur attend (sélection, alignement, styles). L’oublier casse la sélection et lessupports.RichText: un champ éditable inline (gras, italique…) lié à un attribut — l’équivalent d’un input contrôlé riche.
3. save : le HTML stocké
import { useBlockProps, RichText } from '@wordpress/block-editor';
export default function save( { attributes } ) {
const blockProps = useBlockProps.save( { className: 'wpr-livre-une' } );
return (
<div { ...blockProps }>
<RichText.Content tagName="h3" value={ attributes.titre } />
</div>
);
}useBlockProps.save()(variantesave) injecte les classes/attributs côté sortie.RichText.Contentrend la version statique d’unRichText.- Le HTML retourné par
saveest sérialisé danspost_content(entre les commentaireswp:, ch. 3.1).
⚠️ Piège n°1 — l’invalidation de bloc. Si vous modifiez le
saved’un bloc déjà utilisé, le HTML stocké ne correspond plus à ce que produit le nouveau code → WordPress affiche « Ce bloc contient un contenu inattendu ». Pour du contenu statique et figé,saveconvient ; dès que le rendu dépend de données qui évoluent (un livre, un prix, une liste), préférez un bloc dynamique (ch. 8.5) qui ne stocke pas de HTML.
4. Attributs sourcés (statique avancé)
Un attribut peut être extrait du HTML sauvegardé plutôt que stocké dans le commentaire JSON :
"titre": { "type": "string", "source": "html", "selector": "h3" }→ la valeur est lue depuis le <h3> du HTML. C’est ce qui permet aux blocs statiques de rester du HTML propre (ch. 3.1). Sans source, l’attribut est stocké en JSON dans le commentaire d’ouverture. Les blocs dynamiques, eux, stockent tout en attributs (pas de save).
5. Le cycle complet
Pour un bloc dynamique, la dernière partie change : pas de save (ou save renvoie null) → un render.php génère le HTML front à chaque affichage (ch. 8.5).
✏️ Exercices
- Quel est le rôle de
useBlockProps()et que se passe-t-il si on l’oublie ? - Vous créez un bloc qui affiche un livre choisi dans le catalogue (titre, prix).
savestatique ou rendu dynamique ? Pourquoi ? - Comment
setAttributes({ note: 5 })affecte-t-il les autres attributs ?
✅ Solution
useBlockProps()injecte sur l’élément racine les classes et attributs attendus par l’éditeur (sélection, alignement, styles dessupports). L’oublier casse la sélection du bloc et les fonctionnalités natives (couleurs, alignement…).- Rendu dynamique (PHP) : le titre/prix du livre peuvent changer (édition du livre) ; un
savestatique figerait ces valeurs au moment de l’insertion et poserait un problème d’invalidation. Le dynamique recalcule à l’affichage, toujours à jour. setAttributesfait une fusion partielle : il met à journoteet conserve les autres attributs inchangés (comme unsetStated’objet fusionné).
🧠 Quiz de révision
1. Que sont les attributs d’un bloc ?
Son état (déclaré dans block.json), lu via attributes et modifié via setAttributes().
2. setAttributes correspond à quoi en React ?
À setState (avec fusion partielle des attributs).
3. Que produit la fonction save ?
Le HTML sérialisé stocké dans post_content (pour un bloc statique).
4. Qu’est-ce que l’invalidation de bloc et comment l’éviter souvent ?
Un désaccord entre le HTML stocké et le nouveau save ; on l’évite en rendant le bloc dynamique (PHP) pour du contenu variable.
5. À quoi sert source: ‘html’ dans un attribut ?
À extraire la valeur depuis le HTML sauvegardé (plutôt que de la stocker en JSON), gardant un HTML propre.
Chapitre suivant : Contrôles : Inspector & Toolbar.