WordPress est un outil puissant, complet, sécurisé et très modulable. Mais sa modularité est parfois à double tranchant. Parfois pour une feature minime, vous allez être obligé d’installer un plugin assez lourd. Pour éviter cela, voyons un outil que WordPress a mis à notre disposition pour facilement créer des blocs personnalisés pour Gutemberg. De cette façons, non seulement nous obtiendrons vraiment le résultat désiré, et nous garderons un site léger et épuré.

Petit disclaimer, je parle souvent de faire un build/refresh avec un npm run build. Dans le principe vous pouvez vous contenter de faire un npm run start et vous aurez un rebuild automatique. Donc plus besoin de vous soucier du terminal le temps de dev votre module Gutemberg. Cependant j’ai eu 2-3 comportements innatendus avec ça, donc parfois le build va s’avérer plus efficace. Mais n’hésitez pas à utiliser le start, ça vous évitera de relancer un build à chaque modif !

Créer notre base

Bon, je vous passe l’affront de vous expliquer comment installer WordPress. Une fois ceci fait, ouvrez votre terminal, allez dans votre dossier wp-content/plugins et lancez la commande suivante:

npx @wordpress/create-block@latest my-first-block --variant=dynamic

Une fois lancé, allez dans la liste de vos plugins et admirez:

notre premier bloc gutemberg

Vous pouvez l’activer dès maintenant, et nous allons ensuite nous rendre dans une page (vous pouvez en créer une nouvelle pour le test, ou prendre celle par défaut). Tout en bas de votre page, faites un nouveau block et commencez à taper un « / » pour avoir les propositions auto-complétées. Si vous commencez à taper le nom de notre block, vous devriez voir passer le notre:

Si vous sauvegardez votre page et que vous observez votre résultat en live, vous observerez ceci:

  • Le block sur l’éditeur affiche « hello from the editor!« 
  • Le block sur la version publiée affiche « hello from a dynamic block!« 

Ceci nous indique que le rendu depuis l’éditeur et le rendu final sont gérés différemment. Ce qui vous permet de gérer un affichage type « formulaire » pour les admins WordPress et faire un rendu propre pour les utilisateurs finaux. Très pratique, mais comment on gère ça ?

Modifier notre bloc – JSON only

On va commencer par voir les options offertes par cet outil pour modifier le comportement de notre bloc Gutemberg sans produire de code mais en modifiant un fichier JSON. Ouvrons donc notre éditeur de code préféré, et ouvrons notre fichier wp-content/plugins/my-first-block/src/my-first-block/block.json.

Commençons donc par de l’esthétique ! Nous allons modifier la propriété « title » de notre block ainsi que la description. Lancez un petit npm run build dans votre terminal (depuis le bon dossier bien sûr) et en refreshant votre éditeur, vous verrez sous vos yeux ébahis qu’en tapant « / » le nom de votre bloc a changé.

Pas très bluffé ? Dans la partie « supports » en dessous de HTML, ajoutez la couleur et la typo comme suit:

"supports": {
	"html": false,
	"color": {
        "background": true,
        "text": true
    },
    "typography": {
        "fontSize": true
    }
},

Re-build, re-refresh. Et en cliquant sur votre block dans l’éditeur, vous pouvez désormais voir de nouvelles options de style. Jouez un peu avec et observez le résultat depuis le rendu !

Pour une liste complète de ce qui est utilisable, vous pouvez consulter cette doc.

On veut du sérieux, on veut du code !!

C’est partit ! Pour nous challenger un peu on va faire un bloc pour afficher des avis utilisateurs. On utilisera donc des champs text pour le nom et le commentaire et on viendra utiliser un chiffre pour la note. Pour commencer, précisons dans notre block.json les différentes données dont nous allons nous servir. Ajoutons juste après « example »:

"attributes": {
    "name": { "type": "string", "default": "" },
    "review": { "type": "string", "default": "" },
    "rating": { "type": "number", "default": 5 }
}

Ici on a donc une string pour stocker le nom de l’utilisateur, une pour son commentaire et un number pour la note (qu’on met à 5 par défaut parce qu’on ne veut pas trop de mauvais avis).

Maintenant, le stockage. Ouvrons notre edit.js ! Dans l’import de « @wordpress/block-editor » ajoutons « InspectorControls » qui nous permettra de modifier le panel de droite de notre éditeur Gutemberg. Ensuite dans notre fonction Edit, on supprime le contenu de notre <p { …useBlockProps() }> (qu’on va d’ailleurs transformer en div). Dedans nous allons pouvoir insérer une balise <InspectorControls>:

export default function Edit() {
	return (
		<div { ...useBlockProps() }>
			<InspectorControls>
			Hello World
			</InspectorControls>
		</div>
	);
}

Build, refresh et hop ! Maintenant on a deux onglets en cliquant sur notre block: un pour le style (ce qu’on a fait avant) et un pour le contenu avec marqué Hello World ! Insérons donc des choses un peu plus intéressantes.

Pour préparer notre fonction à accueillir nos données, transformons notre fonction comme suit:

export default function Edit({ attributes, setAttributes }) {
	const { name, review, rating } = attributes;
// Le reste de notre fonction

Pour la note, nous allons utiliser une range de 1 à 5. Pour cela nous devons lancer un petit
npm i -s @wordpress/components puis importer les éléments suivants:

import { PanelBody, RangeControl } from '@wordpress/components';

Insérons désormais à la place de « Hello World »

<PanelBody title="Paramètres">
    <RangeControl
        label="Note"
        value={rating}
        onChange={(value) => setAttributes({ rating: value })}
        min={1}
        max={5}
    />
</PanelBody>

Pour les autres données, nous pouvons maintenant ajouter RichText à notre import de ‘@wordpress/block-editor’ et en ajouter deux sous le RangeControl:

<RichText
    tagName="p"
    value={name}
    onChange={(value) => setAttributes({ name: value })}
    placeholder="Nom du client"
/>
<RichText
    tagName="blockquote"
    value={review}
    onChange={(value) => setAttributes({ review: value })}
    placeholder="Avis du client"
/>

Parfait, nos données sont stockées ! Mais comment afficher tout ça ?

Après le stockage, le display

Pour notre éditeur Gutemberg, rien de plus simple ! En dessous de notre fermeture d’InspectorControls, ajoutez le petit bloc suivant:

<div { ...useBlockProps() }>
	<q>{review}</q>
	<p>{'⭐'.repeat(rating)} - {name}</p>
</div>

Ici on vient simplement afficher comme en React les données que l’on rentre dans notre éditeur. Essayez de modifier les données, de sauvegarder et de refresh. Les données devraient bien persister sur l’interface d’édition. Notre fichier edit.js devrait ressembler à la fin à ceci:

import { __ } from '@wordpress/i18n';
import { useBlockProps, InspectorControls, RichText } from '@wordpress/block-editor';
import { PanelBody, RangeControl } from '@wordpress/components';
import './editor.scss';

export default function Edit({ attributes, setAttributes }) {
	const { name, review, rating } = attributes;

	return (
		<div { ...useBlockProps() }>
			<InspectorControls>
				<PanelBody title="Paramètres">
	                <RangeControl
	                    label="Note"
	                    value={rating}
	                    onChange={(value) => setAttributes({ rating: value })}
	                    min={1}
	                    max={5}
	                />
					<RichText
		                tagName="p"
		                value={name}
		                onChange={(value) => setAttributes({ name: value })}
		                placeholder="Nom du client"
		            />
		            <RichText
		                tagName="blockquote"
		                value={review}
		                onChange={(value) => setAttributes({ review: value })}
		                placeholder="Avis du client"
		            />
                </PanelBody>
			</InspectorControls>
			<div { ...useBlockProps() }>
				<q>{review}</q>
				<p>{'⭐'.repeat(rating)} - {name}</p>
			</div>
		</div>
	);
}

Maintenant passons au rendu final. Allons dans notre render.php !

Faisons déjà un petit clean du fichier, on ne garde que la balise <?php et on fait un petit var_dump($attributes); pour voir un peu ce que ça donne.

Ici on peut voir non seulement nos données, mais aussi les données de style que nous avions ajouté plus haut. Ça nous permet de savoir comment utiliser nos données. Nous allons donc aller vraiment au plus simple pour l’affichage. On vérifie que nos données existent, et on display tout (j’ai fait en echo simple pour le tutoriel, n’hésitez pas à faire plus propre de votre côté):

import { __ } from '@wordpress/i18n';
import { useBlockProps, InspectorControls, RichText } from '@wordpress/block-editor';
import { PanelBody, RangeControl } from '@wordpress/components';
import './editor.scss';

export default function Edit({ attributes, setAttributes }) {
	const { name, review, rating } = attributes;

	return (
		<div { ...useBlockProps() }>
			<InspectorControls>
				<PanelBody title="Paramètres">
	                <RangeControl
	                    label="Note"
	                    value={rating}
	                    onChange={(value) => setAttributes({ rating: value })}
	                    min={1}
	                    max={5}
	                />
					<RichText
		                tagName="p"
		                value={name}
		                onChange={(value) => setAttributes({ name: value })}
		                placeholder="Nom du client"
		            />
		            <RichText
		                tagName="blockquote"
		                value={review}
		                onChange={(value) => setAttributes({ review: value })}
		                placeholder="Avis du client"
		            />
                </PanelBody>
			</InspectorControls>
			<div { ...useBlockProps() }>
				<q>{review}</q>
				<p>{'⭐'.repeat(rating)} - {name}</p>
			</div>
		</div>
	);
}

Notons ici que j’affiche aussi le get_block_wrapper_attributes dans ma div pour obtenir directement une jolie série de class WordPress toute faite.

On notera également que niveau sécu c’est pas top-top. Encore une fois pour le tutoriel j’ai fait au plus court. On verra dans un prochain article comment aller plus loin avec create-block et comment faire plus propre au niveau de notre rendu.