Skip to Content

Chapitre 8.3 — edit, save & attributs

⏱️ TL;DR — Les attributs (déclarés dans block.json) sont l’état d’un bloc : edit les lit via attributes et les modifie via setAttributes() (l’équivalent de setState). edit rend l’aperçu éditeur ; save produit le HTML sérialisé stocké dans le contenu. Les deux enveloppent leur racine avec useBlockProps() (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 que save.

🎯 Objectifs

  • Déclarer et typer des attributs.
  • Écrire edit (lecture via attributes, écriture via setAttributes).
  • Écrire save avec useBlockProps.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 Reactattributes = votre state typé (déclaré dans block.json plutôt qu’un useState), 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 les supports.
  • 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() (variante save) injecte les classes/attributs côté sortie.
  • RichText.Content rend la version statique d’un RichText.
  • Le HTML retourné par save est sérialisé dans post_content (entre les commentaires wp:, ch. 3.1).

⚠️ Piège n°1 — l’invalidation de bloc. Si vous modifiez le save d’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é, save convient ; 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

  1. Quel est le rôle de useBlockProps() et que se passe-t-il si on l’oublie ?
  2. Vous créez un bloc qui affiche un livre choisi dans le catalogue (titre, prix). save statique ou rendu dynamique ? Pourquoi ?
  3. Comment setAttributes({ note: 5 }) affecte-t-il les autres attributs ?

✅ Solution

  1. useBlockProps() injecte sur l’élément racine les classes et attributs attendus par l’éditeur (sélection, alignement, styles des supports). L’oublier casse la sélection du bloc et les fonctionnalités natives (couleurs, alignement…).
  2. Rendu dynamique (PHP) : le titre/prix du livre peuvent changer (édition du livre) ; un save statique figerait ces valeurs au moment de l’insertion et poserait un problème d’invalidation. Le dynamique recalcule à l’affichage, toujours à jour.
  3. setAttributes fait une fusion partielle : il met à jour note et conserve les autres attributs inchangés (comme un setState d’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.