Dans les précédents articles de ce blog, nous avons exploré le développement des blocs WordPress sous différents angles. Nous avons examiné le développement de blocs statiques et dynamiques et étendu les fonctionnalités des blocs de base. Cependant, l’approche que nous avons adoptée jusqu’à présent nous a essentiellement permis de créer des blocs standard qui ne réagissaient pas aux interactions de l’utilisateur en temps réel. En bref, ces blocs étaient non interactifs.

Dans cet article, nous allons explorer une nouvelle approche du développement de blocs, qui nous permettra de créer des blocs interactifs grâce à une nouvelle et puissante API de WordPress : l’API d’interactivité de WordPress. Introduite dans WordPress 6.5, cette API vous permet de créer des blocs qui réagissent en temps réel aux interactions des utilisateurs, ce qui vous permet de créer des expériences utilisateur riches et de rendre vos sites attrayants, dynamiques et captivants.

Il y a beaucoup de choses à dire, mais avant de commencer, jetons un coup d’œil aux conditions essentielles !

Ce dont vous avez besoin avant de commencer à utiliser l’API interactivité

Comme l’API interactivité est basée sur React, vous auras besoin d’au moins une connaissance de base du JavaScript côté serveur et de React, ainsi que des outils de construction tels que npm et npx. Vous aurez également besoin d’une compréhension approfondie du développement WordPress et de l’éditeur de blocs Gutenberg.

Une fois que vous aurez acquis les compétences nécessaires, vous aurez besoin d’un environnement de développement local qui vous permette de lancer rapidement et facilement un site WordPress. Nous vous recommandons DevKinsta, notre suite de développement local conçue spécifiquement pour WordPress. Avec DevKinsta, vous pouvez mettre en place un nouveau site WordPress local en quelques clics et le personnaliser en détail.

Lorsque vous créez un nouveau projet WordPress dans DevKinsta, vous pouvez définir les options suivantes :

  • Domaine de premier niveau : Par défaut .local
  • Version PHP
  • Nom de la base de données
  • Activer HTTPS
  • Détails de WordPress
  • Mise à jour automatique de WordPress
  • Multisite

En outre, vous pouvez importer un site MyKinsta existant à partir d’une sauvegarde.

Configuration d'un site web local dans DevKinsta
Configuration d’un site web local dans DevKinsta

Qu’est-ce que l’API d’interactivité ?

L’API d’interactivité est une API native de WordPress qui permet d’ajouter de l’interactivité aux blocs Gutenberg et, par conséquent, aux articles et aux pages d’un site WordPress. Il s’agit d’une solution légère et moderne qui adopte une approche déclarative pour gérer les interactions avec les utilisateurs.

La création d’un bloc interactif à partir de zéro nécessite des compétences avancées en matière de développement PHP et JavaScript côté serveur. Cependant, il n’est pas nécessaire de réinventer la roue à chaque nouveau projet, car WordPress fournit un modèle pour la création de blocs interactifs :

npx @wordpress/create-block --template @wordpress/create-block-interactive-template

Ce modèle comprend tout ce dont vous avez besoin pour échafauder un bloc interactif, y compris deux exemples de travail que vous pouvez utiliser comme référence pour votre premier projet : un bouton pour basculer le thème actuel et un bouton pour développer/réduire un paragraphe.

Pour commencer, ouvrez votre outil de ligne de commande préféré, navigue jusqu’au répertoire Plugins de votre installation locale de WordPress, et saisissez ce qui suit :

npx @wordpress/create-block your-interactive-block --template @wordpress/create-block-interactive-template

Laissez quelques instants pour que l’installation se termine, puis ouvrez votre dossier de projet à l’aide de votre éditeur de code préféré. Nous vous recommandons d’utiliser Visual Studio Code, mais vous pouvez utiliser l’éditeur avec lequel vous vous sentez le plus à l’aise.

Le projet de bloc interactif fourni par le site <code>@wordpress/create-block-interactive-template</code>
Le projet de bloc interactif fourni par le site @wordpress/create-block-interactive-template

À partir de la ligne de commande, naviguez jusqu’au dossier de la nouvelle extension et démarrez le serveur de développement à l’aide de la commande suivante :

npm start

À partir de maintenant, toutes les modifications que vous apporterez à votre bloc seront visibles en temps réel dans votre installation WordPress.

Ensuite, dans votre administration WordPress, naviguez vers l’écran Extensions et activez l’extension Interactivity API que vous venez de créer. Créez un nouvel article ou une nouvelle page, puis recherchez Votre bloc interactif dans l’insertion de blocs et ajoutez-la à votre contenu. Sauvegardez la publication et prévisualisez-la sur l’interface publique. Vous verrez un bloc jaune contenant deux boutons. Le premier bouton change la couleur d’arrière-plan du bloc, et le deuxième bouton affiche ou masque le contenu du paragraphe.

An example interactive block
Un exemple de bloc interactif fourni par le site @wordpress/create-block-interactive-template

Maintenant que vous avez une extension à laquelle vous référer pour les sujets abordés dans cet article, nous pouvons passer à autre chose et explorer plus en profondeur les blocs interactifs.

La structure des blocs interactifs

La structure des blocs interactifs est la même que celle des blocs traditionnels. Vous aurez toujours besoin d’un fichier package.json, d’un fichier block.json, d’un fichier edit.js et d’un fichier style.scss. En outre, vous aurez besoin d’un fichier render.php pour le rendu côté serveur et d’un fichier view.js pour gérer l’interactivité frontale.

Examinons les briques spécifiques d’un bloc interactif en décomposant les fichiers individuels du projet de démarrage.

package.json

Le fichier package.json est utilisé dans les projets Node pour identifier votre projet, gérer les scripts et gérer et installer les dépendances pendant le développement.

Ce qui suit est le package.json pour le bloc interactif fourni par le create-block-interactive-template:

{
	"name": "your-interactive-block",
	"version": "0.1.0",
	"description": "An interactive block with the Interactivity API.",
	"author": "The WordPress Contributors",
	"license": "GPL-2.0-or-later",
	"main": "build/index.js",
	"scripts": {
		"build": "wp-scripts build --experimental-modules",
		"format": "wp-scripts format",
		"lint:css": "wp-scripts lint-style",
		"lint:js": "wp-scripts lint-js",
		"packages-update": "wp-scripts packages-update",
		"plugin-zip": "wp-scripts plugin-zip",
		"start": "wp-scripts start --experimental-modules"
	},
	"dependencies": {
		"@wordpress/interactivity": "latest"
	},
	"files": [
		"[^.]*"
	],
	"devDependencies": {
		"@wordpress/scripts": "^30.24.0"
	}
}

Les sections scripts et dependencies sont particulièrement importantes ici.

  • build: Compile le code source en JavaScript pour la production. L’option --experimental-modules permet de prendre en charge les modules de script WordPress.
  • start: Démarre le serveur de développement. Notez que l’option --experimental-modules est à nouveau spécifiée.
  • dependencies: Inclut les dépendances d’exécution avec le dernier paquetage de l’API Interactivité.

block.json

Le fichier block.json est le manifeste de votre bloc Gutenberg. Il spécifie les métadonnées, les médias, les scripts et les styles à charger. Par défaut, le create-block-interactive-template génère le block.json suivant :

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 3,
	"name": "create-block/your-interactive-block",
	"version": "0.1.0",
	"title": "Your Interactive Block",
	"category": "widgets",
	"icon": "media-interactive",
	"description": "An interactive block with the Interactivity API.",
	"example": {},
	"supports": {
		"interactivity": true
	},
	"textdomain": "your-interactive-block",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css",
	"render": "file:./render.php",
	"viewScriptModule": "file:./view.js"
}

Les champs suivants sont essentiels pour un bloc interactif :

  • apiVersion: 3 est la dernière version de l’API du bloc et prend en charge les dernières fonctionnalités du bloc, telles que les modules de script.
  • supports: Spécifie les supports de bloc. "interactivity": true ajoute la prise en charge de l’API d’interactivité.
  • render: Spécifie le fichier PHP responsable du rendu dans l’interface publique. C’est dans ce fichier que vous ajoutez les directives qui rendent un bloc interactif.
  • viewScriptModule: Spécifie le fichier JavaScript qui contient la logique d’interactivité. Ce fichier n’est chargé que sur l’interface publique et seulement si la page contient le bloc interactif.

render.php

render.php est l’endroit où vous construisez le balisage d’un bloc dynamique. Pour rendre votrre bloc interactif, vous devez ajouter des attributs qui rendent les éléments DOM de votre bloc interactif.

Le fichier render.php du projet de démarrage ressemble à ce qui suit :

<?php
/**
 * PHP file to use when rendering the block type on the server to show on the front end.
 *
 * The following variables are exposed to the file:
 *     $attributes (array): The block attributes.
 *     $content (string): The block default content.
 *     $block (WP_Block): The block instance.
 *
 * @see https://github.com/WordPress/gutenberg/blob/trunk/docs/reference-guides/block-api/block-metadata.md#render
 */

// Generates a unique id for aria-controls.
$unique_id = wp_unique_id( 'p-' );

// Adds the global state.
wp_interactivity_state(
	'create-block',
	array(
		'isDark'    => false,
		'darkText'  => esc_html__( 'Switch to Light', 'your-interactive-block' ),
		'lightText' => esc_html__( 'Switch to Dark', 'your-interactive-block' ),
		'themeText'	=> esc_html__( 'Switch to Dark', 'your-interactive-block' ),
	)
);
?>

<div
	<?php echo get_block_wrapper_attributes(); ?>
	data-wp-interactive="create-block"
	<?php echo wp_interactivity_data_wp_context( array( 'isOpen' => false ) ); ?>
	data-wp-watch="callbacks.logIsOpen"
	data-wp-class--dark-theme="state.isDark"
>
	<button
		data-wp-on--click="actions.toggleTheme"
		data-wp-text="state.themeText"
	></button>

	<button
		data-wp-on--click="actions.toggleOpen"
		data-wp-bind--aria-expanded="context.isOpen"
		aria-controls="<?php echo esc_attr( $unique_id ); ?>"
	>
		<?php esc_html_e( 'Toggle', 'your-interactive-block' ); ?>
	</button>

	<p
		id="<?php echo esc_attr( $unique_id ); ?>"
		data-wp-bind--hidden="!context.isOpen"
	>
		<?php
			esc_html_e( 'Your Interactive Block - hello from an interactive block!', 'your-interactive-block' );
		?>
	</p>
</div>

Voici ce que fait ce code :

  • wp_interactivity_state: Obtient et/ou définit l’état global initial d’un magasin Interactivity API.
  • data-wp-interactive: Active l’API d’interactivité sur l’élément DOM et ses enfants. Sa valeur doit être l’espace de noms unique de votre plugin ou de votre bloc.
  • wp_interactivity_data_wp_context(): Génère la directive data-wp-context, qui fournit un état local à un nœud HTML spécifique et à ses enfants.
  • data-wp-watch: Exécute un rappel lorsqu’un nœud est créé et à chaque fois que l’état ou le contexte change.
  • data-wp-class--dark-theme: Ajoute ou supprime la classe dark-theme à l’élément HTML.
  • data-wp-on--click: Exécute le code de manière synchrone sur l’évènement de clic.
  • data-wp-text: Définit le texte intérieur de l’élément HTML.
  • data-wp-bind--aria-expanded et data-wp-bind--hidden: Définit les attributs HTML (aria-expanded et hidden) sur les éléments correspondants en fonction d’une valeur booléenne ou d’une chaîne de caractères.

view.js

Ce fichier définit le Store qui contient la logique et les données nécessaires au comportement du bloc, y compris l’état, les actions et les rappels.

Voici le fichier view.js généré par le projet de démarrage :

/**
 * WordPress dependencies
 */
import { store, getContext } from '@wordpress/interactivity';

const { state } = store( 'create-block', {
	state: {
		get themeText() {
			return state.isDark ? state.darkText : state.lightText;
		},
	},
	actions: {
		toggleOpen() {
			const context = getContext();
			context.isOpen = ! context.isOpen;
		},
		toggleTheme() {
			state.isDark = ! state.isDark;
		},
	},
	callbacks: {
		logIsOpen: () => {
			const { isOpen } = getContext();
			// Log the value of `isOpen` each time it changes.
			console.log( `Is open: ${ isOpen }` );
		},
	},
} );
  • store: La fonction principale utilisée pour créer et enregistrer l’état global et la logique du bloc.
  • getContext: Une fonction utilisée dans les actions et les rappels pour accéder à l’état local (le context) de l’élément DOM qui a déclenché l’évènement.
  • state: Définit les données réactives globales du bloc.
  • actions: Comprend les fonctions qui définissent la logique et modifient l’état.
  • callbacks: Comprend les fonctions à exécuter en réponse à des évènements spécifiques ou à des changements d’état de façon automatique.

Cela fait beaucoup à assimiler, mais ne vous inquiétez pas ! Tout deviendra plus clair une fois que vous aurez lu les sections suivantes.

Examinons maintenant les concepts clés de l’API d’interactivité : directives, magasin, état, actions et rappels.

Directives de l’API Interactivité

Comme d’autres bibliothèques frontales telles que Alpine.js et Vue.js, l’API Interactivité utilise des attributs HTML spéciaux qui te permettent de répondre aux évènements de la page, de mettre à jour l’état de l’application, de manipuler le DOM, d’appliquer des styles CSS, de gérer les entrées de l’utilisateur, et bien d’autres choses encore.

Ces attributs sont appelés directives et vous permettent de connecter votre balisage à la logique JavaScript sous-jacente.

Vous trouverez ci-dessous une liste des directives que vous utiliserez le plus souvent.

Fonction Directive Description de la directive
Activation/espace de noms data-wp-interactive Active l’API pour l’élément et ses enfants. La valeur doit être définie sur l’identifiant unique de votre extension.
État local data-wp-context Fournit un état local (« contexte ») pour l’élément actuel et tous ses enfants. Il accepte un objet JSON. Il est recommandé d’utiliser wp_interactivity_data_wp_context() pour le définir en PHP (typiquement render.php).
Attribut Binding data-wp-bind--[attribute] Définit un attribut HTML (par exemple, disabled, value) en fonction d’un état réactif ou d’une valeur de contexte (une valeur booléenne ou une valeur de chaîne).
Modification du texte data-wp-text Définit le contenu textuel interne de l’élément. Elle n’accepte que les chaînes de caractères.
Basculement de classe CSS data-wp-class--[classname] Ajoute ou supprime une classe CSS en fonction d’une valeur booléenne.
Style en ligne data-wp-style--[css-property] Ajoute ou supprime une classe de style en ligne en fonction d’une valeur booléenne.
Gestion des événements data-wp-on--[event] Exécute le code en réponse aux évènements DOM standard tels que click ou mouseover.
Exécution initiale data-wp-init Exécute une fonction de rappel une seule fois, uniquement lorsque le nœud est créé.
Surveillance de l’état data-wp-watch Exécute une fonction de rappel lors de la création du nœud et à nouveau lorsque l’état ou le contexte change.
Itération de liste data-wp-each Rend une liste d’éléments.

Pour obtenir une liste complète des directives, consultez les notes de développement de l’API Interactivity et la référence de l’API.

État global, contexte local et état dérivé

Avant de commencer à utiliser l’API Interactivity, il est essentiel que vous vous familiarisiez avec les concepts fondamentaux de la gestion des états dans le développement frontend. Ceux qui développent régulièrement avec React, Vue ou Angular seront déjà familiarisés avec ces concepts. Pour ceux qui découvrent ces technologies, il peut être utile de donner quelques définitions générales.

État global

L’état global fait référence à l’ensemble des données accessibles depuis presque tous les composants d’une application. Dans le cas de l’API Interactivité, par exemple, l’état global affecte tous les blocs interactifs de la page, en les maintenant synchronisés. Par exemple, lorsqu’un utilisateur ajoute un produit à son panier, cela se répercute sur le bloc du panier.

Lorsque vous utilisez l’API Interactivity, vous devez définir les valeurs initiales de l’état global sur le serveur à l’aide de la fonction wp_interactivity_state(). Dans le projet de démarrage décrit ci-dessus, cette fonction est utilisée dans le fichier render.php comme ceci :

// Adds the global state.
wp_interactivity_state(
	'create-block',
	array(
		'isDark'    => false,
		'darkText'  => esc_html__( 'Switch to Light', 'your-interactive-block' ),
		'lightText' => esc_html__( 'Switch to Dark', 'your-interactive-block' ),
		'themeText'	=> esc_html__( 'Switch to Dark', 'your-interactive-block' ),
	)
);

Cette fonction accepte deux arguments :

  • Un identifiant unique pour l’espace de noms du magasin. Dans ce cas, create-block.
  • Un tableau de données qui sera fusionné avec l’espace de noms du magasin existant, s’il existe.

Les valeurs initiales de l’état global sont ensuite utilisées pour le rendu de la page. Vous pouvez accéder directement aux valeurs de l’état global en utilisant state dans les valeurs des attributs de la directive, comme dans le code suivant :

<button
	data-wp-on--click="actions.toggleTheme"
	data-wp-text="state.themeText"
></button>

La fonction store() constitue le principal point d’accès à l’état global à partir de JavaScript, limité à l’espace de noms sélectionné. Pour revenir au code du projet de démarrage, la fonction store() est utilisée dans le fichier view.js comme ceci :

import { store, getContext } from '@wordpress/interactivity';

const { state } = store( 'create-block', {
	state: { ... },
	actions: { ... },
	callbacks: { ... },
} );

Pour accéder à l’état global, vous pouvez utiliser la propriété state:

actions: {
	toggleTheme() {
		state.isDark = ! state.isDark;
	},
},

Contexte local

Le contexte local est une donnée à laquelle ne peuvent accéder qu’un composant spécifique et ses enfants directs. Un bloc interactif WordPress fournit un état indépendant pour le bloc et ses éléments imbriqués.

Lorsque vous utilisez l’API Interactivity, vous pouvez accéder au contexte local à l’aide de la fonction getContext(). Si l’on se réfère à nouveau au projet de démarrage, lorsque l’utilisateur clique sur le bouton Toggle, l’action toggleOpen() est déclenchée, ce qui permet d’accéder au contexte local du composant :

actions: {
	toggleOpen() {
		const context = getContext();
		context.isOpen = ! context.isOpen;
	},
},
  • getContext(): Récupère l’objet d’état local du bloc. Les propriétés de cet objet sont définies dans le balisage du composant (render.php) à l’aide de la fonction wp_interactivity_data_wp_context().
  • context.isOpen = ! context.isOpen;: Change la valeur de la propriété isOpen dans le contexte local du composant.

État dérivé

L’état dérivé fait référence aux données calculées dynamiquement à partir de l’état global ou local existant.

Par exemple, jettez un coup d’œil au code du fichier view.js, en particulier dans cette section :

const { state } = store( 'create-block', {
	state: {
		get themeText() {
			return state.isDark ? state.darkText : state.lightText;
		},
	},
	...
}

Ce bloc définit l’état dérivé themeText dans l’état global défini dans l’espace de noms create-block.

  • get themeText() n’est pas une valeur fixe, mais plutôt une fonction qui est exécutée chaque fois que tu essaies de lire la propriété themeText. Elle ne doit pas être invoquée comme une fonction normale car l’API Interactivity la traite comme une propriété d’état et recalcule automatiquement sa valeur chaque fois que les valeurs des autres propriétés d’état changent. Dans le code ci-dessus, la valeur de la propriété themeText est recalculée chaque fois que la valeur de la propriété isDark change. Si state.isDark est true, alors themeText prend la valeur de state.darkText; sinon, il prend la valeur de state.lightText.

Pour un aperçu plus complet des concepts décrits dans cette section, voir Comprendre l’état global, le contexte local et l’état dérivé.

Actions et rappels

Les actions et les rappels déterminent la réponse à l’interaction de l’utilisateur et aux changements d’état.

La section actions d’un bloc interactif contient des fonctions qui sont exécutées en réponse aux évènements générés par l’utilisateur. Ces fonctions servent principalement à modifier l’état local ou global du composant. Prenez le code suivant dans le fichier view.js :

actions: {
	toggleOpen() {
		const context = getContext();
		context.isOpen = ! context.isOpen;
	},
	...
},
  • Dans cette section du code, la fonction toggleOpen() utilise getContext() pour accéder au contexte local du bloc qui a déclenché l’action pour changer la valeur de la propriété isOpen.

De la même façon, vous pouvez accéder à l’état global :

actions: {
	...,
	toggleTheme() {
		state.isDark = ! state.isDark;
	},
},
  • La fonction toggleTheme() accède directement à l’objet global state et modifie la valeur de la propriété isDark.

Les actions sont déclenchées par la directive data-wp-on--[event]. Par exemple, dans le fichier render.php, vous trouverez le bouton suivant :

<button
	data-wp-on--click="actions.toggleOpen"
	data-wp-bind--aria-expanded="context.isOpen"
	aria-controls="<?php echo esc_attr( $unique_id ); ?>"
>
  • Dans ce code HTML, l’attribut data-wp-on--click active l’action toggleOpen lorsque l’utilisateur clique sur le bouton à bascule.

La section callbacks contient des fonctions qui sont exécutées automatiquement lorsque les données dont elles dépendent changent. Leur but est de produire des effets secondaires en réponse à un changement d’état.

Dans le projet de base généré par create-block-interactive-template, vous trouverez le rappel suivant :

callbacks: {
	logIsOpen: () => {
		const { isOpen } = getContext();
		// Log the value of `isOpen` each time it changes.
		console.log( `Is open: ${ isOpen }` );
	},
},
  • La fonction logIsOpen utilise la variable isOpen, qui est disponible dans le contexte Local.
  • Le callback récupère la valeur de isOpen à l’aide de getContext().
  • Chaque fois que la valeur de isOpen change, la fonction envoie un message à la console du navigateur.
Un message dans la console informe l'utilisateur de la modification du contexte Local.
Un message dans la console informe l’utilisateur de la modification du contexte Local.

Comment construire un bloc interactif

Maintenant que nous avons abordé la théorie, il est temps de commencer à s’amuser avec le code ! Dans la deuxième partie de ce guide, vous apprendrez à créer un bloc interactif qui permet aux utilisateurs d’ajouter des produits à un panier idéal, avec des quantités et des totaux qui se mettent à jour automatiquement. Il s’agit d’un exemple de démonstration, mais nous espérons qu’il vous permettra de bien comprendre comment utiliser l’état, les actions et les rappels.

Le bloc interactif dans l'éditeur
Le bloc interactif dans l’éditeur

Nous allons créer un bloc appelé Compteur interactif à l’aide de create-block-interactive-template. Pour commencer, ouvrez votre outil de ligne de commande et saisissez ceci :

npx @wordpress/create-block interactive-counter --template @wordpress/create-block-interactive-template

Ensuite, naviguez dans le répertoire de votre nouveau projet et exécutez la première compilation.

cd interactive-counter && npm run build

Ouvrez maintenant le projet dans votre éditeur de code. Dans le répertoire /src, cherchez le fichier block.json. Il devrait ressembler à ceci :

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 3,
	"name": "create-block/interactive-counter",
	"version": "0.1.0",
	"title": "Interactive Counter",
	"category": "widgets",
	"icon": "media-interactive",
	"description": "An interactive block with the Interactivity API.",
	"supports": {
		"interactivity": true
	},
	"textdomain": "interactive-counter",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css",
	"render": "file:./render.php",
	"viewScriptModule": "file:./view.js"
}

N’hésitez pas à le personnaliser, mais veillez à ne pas modifier les champs essentiels décrits ci-dessus.

Le fichier edit.js

L’étape suivante consiste à créer le bloc qui apparaîtra dans l’éditeur. Pour cela, vous devez éditer le fichier /src/edit.js. Ouvrez le fichier et modifiez-le comme ceci :

import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';

export default function Edit({ attributes, setAttributes }) {
	const blockProps = useBlockProps();
	const products = [
		{ id: 'product1', name: __('Product 1', 'interactive-counter'), price: 10.00 },
		{ id: 'product2', name: __('Product 2', 'interactive-counter'), price: 15.00 },
		{ id: 'product3', name: __('Product 3', 'interactive-counter'), price: 20.00 },
	];

	return (
		<div {...blockProps}>
			<h3>{__('Shopping Cart', 'interactive-counter')}</h3>
			<ul>
				{products.map((product) => (
					<li key={product.id} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '10px' }}>
						<span style={{ flex: 1 }}>{product.name} - ${product.price.toFixed(2)}</span>
						<div style={{ display: 'flex', gap: '10px', alignItems: 'center' }}>
							<button disabled>-</button>
							<span>0</span>
							<button disabled>+</button>
						</div>
						<span style={{ flex: 1, textAlign: 'right' }}>
							{__('Subtotal:', 'interactive-counter')} $0.00
						</span>
					</li>
				))}
			</ul>
			<div style={{ borderTop: '1px solid #ccc', paddingTop: '15px' }}>
				<p style={{ display: 'flex', justifyContent: 'space-between' }}>
					<strong>{__('Subtotal:', 'interactive-counter')}</strong>
					<span>$0.00</span>
				</p>
				<p style={{ display: 'flex', justifyContent: 'space-between' }}>
					<strong>{__('Tax (22%):', 'interactive-counter')}</strong>
					<span>$0.00</span>
				</p>
				<p style={{ display: 'flex', justifyContent: 'space-between' }}>
					<strong>{__('Total:', 'interactive-counter')}</strong>
					<span>$0.00</span>
				</p>
			</div>
			<p>{__('Quantities and totals will be interactive in the frontend.', 'interactive-counter')}</p>
		</div>
	);
}

Ce code génère un bloc personnalisé dans le backend. Le bloc ne sera interactif que dans le frontend. Pour plus de détails sur le fichier /src/edit.js, vous pouvez vous référer à nos guides de développement des blocs Gutenberg.

Le fichier render.php

Le prochain fichier à modifier est /src/render.php. Ouvrez le fichier et remplacez le code existant par ce qui suit :

<?php
/**
 * Render callback for the interactive-counter block.
 */

$products = [
	['id' => 'product1', 'name' => __('Product 1', 'interactive-counter'), 'price' => 10.00],
	['id' => 'product2', 'name' => __('Product 2', 'interactive-counter'), 'price' => 15.00],
	['id' => 'product3', 'name' => __('Product 3', 'interactive-counter'), 'price' => 20.00],
];

// Initialize global state
wp_interactivity_state('interactive-counter', [
	'products' => array_map(function ($product) {
		return [
			'id' => $product['id'],
			'name' => $product['name'],
			'price' => $product['price'],
			'quantity' => 0,
			'subtotal' => '0.00',
		];
	}, $products),
	'vatRate' => 0.22,
]);

Voici ce que fait ce code :

  • Tout d’abord, il crée un tableau de produits codé en dur. Chaque produit a un identifiant, un nom et un prix.
  • Ensuite, il initialise l’état Global avec wp_interactivity_state. Le premier paramètre est le nom du magasin, qui doit correspondre à celui utilisé dans view.js.
  • Ensuite, il fait correspondre le tableau de produits précédent à un nouveau tableau products, en ajoutant la quantité et le sous-total aux propriétés du tableau d’origine. Ce nouveau tableau fournit la structure de données que vous utiliserez dans view.js.
  • vatRate définit la valeur par défaut pour le calcul de la taxe.

Ensuite, ajoutez ce qui suit au code ci-dessus :

<div <?php echo get_block_wrapper_attributes(); ?> data-wp-interactive="interactive-counter" data-wp-init="callbacks.init">
	<h3><?php echo esc_html__('Cart', 'interactive-counter'); ?></h3>
	<ul>
		<?php foreach ($products as $index => $product) : ?>
			<li data-wp-context='{
				"productId": "<?php echo esc_attr($product['id']); ?>",
				"quantity": 0,
				"subtotal": "0.00"
			}' 
			data-wp-bind--data-wp-context.quantity="state.products[<?php echo $index; ?>].quantity" 
			data-wp-bind--data-wp-context.subtotal="state.products[<?php echo $index; ?>].subtotal">
				<span class="product-name"><?php echo esc_html($product['name']); ?> - $<?php echo esc_html(number_format($product['price'], 2)); ?></span>
				<div class="quantity-controls">
					<button data-wp-on--click="actions.decrement">-</button>
					<span data-wp-text="context.quantity">0</span>
					<button data-wp-on--click="actions.increment">+</button>
				</div>
				<span class="product-subtotal">
					<?php echo esc_html__('Subtotal:', 'interactive-counter'); ?>
					$<span data-wp-text="context.subtotal">0.00</span>
				</span>
			</li>
		<?php endforeach; ?>
	</ul>
	<div class="totals">
		<p>
			<strong><?php echo esc_html__('Subtotal:', 'interactive-counter'); ?></strong>
			$ <span data-wp-text="state.subtotal">0.00</span>
		</p>
		<p>
			<strong><?php echo esc_html__('Tax (22%):', 'interactive-counter'); ?></strong>
			$ <span data-wp-text="state.vat">0.00</span>
		</p>
		<p>
			<strong><?php echo esc_html__('Total:', 'interactive-counter'); ?></strong>
			$ <span data-wp-text="state.total">0.00</span>
		</p>
	</div>
</div>

Voici ce que fait ce code :

  • La fonction get_block_wrapper_attributes() dans le conteneur div est une fonction WordPress qui génère les attributs standard d’un bloc. Dans ce cas, elle génère l’attribut de classe "wp-block-create-block-interactive-counter".
  • L’attribut data-wp-interactive rend ce bloc interactif.
  • L’attribut data-wp-init déclenche le rappel init défini dans view.js.
  • La boucle foreach génère un élément de liste pour chaque produit du tableau products.
  • data-wp-context définit le contexte local du bloc.
  • data-wp-bind lie la valeur de data-wp-context.quantity à la propriété globale state.products[$index].quantity.
  • La même chose se produit dans la ligne ci-dessous avec le sous-total.
  • Les deux boutons suivants activent les actions decrement et increment grâce à l’attribut data-wp-on--click.
  • L’attribut data-wp-text dans le span met à jour le contenu de l’élément en fonction de la valeur actuelle de context.quantity.

Le reste du code est explicite, passons donc au fichier suivant.

Le fichier view.js

Ce fichier contient la logique de votre bloc interactif.

import { store, getContext } from '@wordpress/interactivity';

store('interactive-counter', {
	state: {
		get subtotal() {
			const { products } = store('interactive-counter').state;
			return products
				.reduce((sum, product) => sum + product.price * (product.quantity || 0), 0)
				.toFixed(2);
		},
		get vat() {
			const { subtotal, vatRate } = store('interactive-counter').state;
			return (subtotal * vatRate).toFixed(2);
		},
		get total() {
			const { subtotal, vat } = store('interactive-counter').state;
			return (parseFloat(subtotal) + parseFloat(vat)).toFixed(2);
		},
	},
	actions: {
		increment: () => {
			const context = getContext();
			const { products } = store('interactive-counter').state;
			const product = products.find(p => p.id === context.productId);
			if (product) {
				product.quantity = (product.quantity || 0) + 1;
				product.subtotal = (product.price * product.quantity).toFixed(2);
				context.quantity = product.quantity;
				context.subtotal = product.subtotal;
				console.log(`Incremented ${context.productId}:`, { quantity: product.quantity, subtotal: product.subtotal, context });
			} else {
				console.warn('Product not found:', context.productId);
			}
		},
		decrement: () => {
			const context = getContext();
			const { products } = store('interactive-counter').state;
			const product = products.find(p => p.id === context.productId);
			if (product && (product.quantity || 0) > 0) {
				product.quantity -= 1;
				product.subtotal = (product.price * product.quantity).toFixed(2);
				context.quantity = product.quantity;
				context.subtotal = product.subtotal;
				console.log(`Decremented ${context.productId}:`, { quantity: product.quantity, subtotal: product.subtotal, context });
			} else {
				console.warn('Cannot decrement:', context.productId, product?.quantity);
			}
		},
	},
	callbacks: {
		init: () => {
			const { products } = store('interactive-counter').state;
			products.forEach((product, index) => {
				product.quantity = 0;
				product.subtotal = '0.00';
				console.log(`Initialized product ${index}:`, { id: product.id, quantity: product.quantity, subtotal: product.subtotal });
			});
		},
	},
});

Ce fichier définit le magasin de l’espace de noms interactive-counter. Il gère l’état, les actions et les rappels :

store('interactive-counter', {
	state: { ... },
	actions: { ... },
	callbacks: { ... },
});

Voyons cela de plus près.

  • state: Définit trois propriétés d’état calculées (getters) : subtotal, vat, et total. Ces fonctions récupèrent les valeurs de l’état global et calculent les valeurs à renvoyer.
  • actions: Définit deux fonctions exécutées sur des événements : increment et decrement. Ces fonctions récupèrent le tableau products dans l’état global, récupèrent le produit actuel dans le contexte local en fonction de context.productId, mettent à jour les valeurs des propriétés du produit actuel (quantity et subtotal) et synchronisent le contexte local avec les nouvelles valeurs.
  • callbacks: Définit un rappel init pour l’initialisation.

L’image suivante montre le bloc interactif dans le frontend.

Un compteur interactif construit avec l'API Interactivity
Un compteur interactif construit avec l’API Interactivity

Résumé

Dans cet article, nous avons présenté les principales fonctionnalités de l’API d’interactivité de WordPress. Nous avons approfondi des concepts clés tels que l’état global, le contexte local, les directives, les actions et les rappels. Vous avez appris à créer un bloc interactif à partir de zéro à l’aide de @wordpress/create-block-interactive-template, et nous avons mis cela en pratique en créant un vrai bloc qui interagit avec les entrées de l’utilisateur.

Nous espérons vous avoir fourni les outils et les connaissances nécessaires pour créer des sites web WordPress fantastiques, dynamiques et interactifs à l’aide de l’API d’interactivité de WordPress.

Bon codage !

Carlo Daniele Kinsta

Carlo est un passionné de webdesign et de développement frontend. Il joue avec WordPress depuis plus de 10 ans, notamment en collaboration avec des universités et des établissements d'enseignement italiens et européens. Il a écrit des dizaines d'articles et de guides sur WordPress, publiés à la fois sur des sites web italiens et internationaux, ainsi que dans des magazines imprimés. Vous pouvez trouver Carlo sur X et LinkedIn.