# Filtres JavaScript de blocs : étendre les blocs natifs sans les forker

> Ajouter un attribut et un contrôle à un bloc core sans jamais toucher à son code source, grâce à blocks.registerBlockType, editor.BlockEdit et extraProps.

- Auteur : Clément Hadrot
- Publié le : 2020-08-19
- Mis à jour le : 2020-08-19
- Catégorie : Blocs Gutenberg
- URL : https://wpmoderne.dev.wordpress-developpement.fr/blocs/filtres-javascript-blocs-etendre-blocs-natifs/

## L’essentiel

- Trois filtres suffisent à étendre n'importe quel bloc natif
- Aucun besoin de recréer un bloc pour ajouter un simple réglage
- Les filtres s'appliquent à tous les blocs, natifs ou tiers

Un besoin qui revient régulièrement en agence : ajouter une classe CSS conditionnelle au bloc Paragraphe natif, sans dupliquer tout son code pour en faire un bloc maison. La réponse ne passe pas par un fork du bloc, ni par un remplacement complet : le système de filtres JavaScript de Gutenberg, calqué sur les hooks PHP de WordPress, permet d'intercepter le cycle de vie de n'importe quel bloc, natif ou tiers, à trois moments précis.

## Le principe : addFilter comme add_filter

Le paquet `@wordpress/hooks` expose `addFilter`, qui fonctionne exactement comme son équivalent PHP : un nom de filtre, un espace de nom unique, une fonction qui reçoit une valeur et la renvoie modifiée.

```
import { addFilter } from '@wordpress/hooks';
```

## Filtre 1 : blocks.registerBlockType, pour ajouter un attribut

```
function ajouterAttribut( settings, name ) {
	if ( name !== 'core/paragraph' ) {
		return settings;
	}
	return {
		...settings,
		attributes: {
			...settings.attributes,
			classePersonnalisee: {
				type: 'string',
				default: '',
			},
		},
	};
}

addFilter(
	'blocks.registerBlockType',
	'mon-projet/paragraphe-classe',
	ajouterAttribut
);
```

Ce filtre s'exécute au moment de l'enregistrement du bloc, avant même qu'un éditeur n'existe. Le test sur `name` est indispensable : sans lui, l'attribut s'ajouterait à tous les blocs du site, y compris ceux qui n'en ont aucun besoin.

## Filtre 2 : editor.BlockEdit, pour ajouter le contrôle

> L'essentiel à retenir : Trois filtres suffisent à étendre n'importe quel bloc natif ; Aucun besoin de recréer un bloc pour ajouter un simple réglage ; Les filtres s'appliquent à tous les blocs, natifs ou tiers

```
import { InspectorControls } from '@wordpress/block-editor';
import { PanelBody, TextControl } from '@wordpress/components';
import { createHigherOrderComponent } from '@wordpress/compose';

const ajouterControle = createHigherOrderComponent( ( BlockEdit ) => {
	return ( props ) => {
		if ( props.name !== 'core/paragraph' ) {
			return <BlockEdit { ...props } />;
		}
		return (
			<>
				<BlockEdit { ...props } />
				<InspectorControls>
					<PanelBody title="Classe personnalisée">
						<TextControl
							value={ props.attributes.classePersonnalisee }
							onChange={ ( classePersonnalisee ) =>
								props.setAttributes( { classePersonnalisee } )
							}
						/>
					</PanelBody>
				</InspectorControls>
			</>
		);
	};
}, 'ajouterControle' );

addFilter( 'editor.BlockEdit', 'mon-projet/paragraphe-controle', ajouterControle );
```

`createHigherOrderComponent` enrobe le composant d'édition d'origine sans le remplacer : il reste responsable de tout son rendu habituel, seul un `InspectorControls` supplémentaire vient s'y greffer.

## Filtre 3 : blocks.getSaveContent.extraProps, pour le rendu final

```
function ajouterProps( extraProps, blockType, attributes ) {
	if ( blockType.name !== 'core/paragraph' ) {
		return extraProps;
	}
	if ( attributes.classePersonnalisee ) {
		extraProps.className = (
			( extraProps.className || '' ) + ' ' + attributes.classePersonnalisee
		).trim();
	}
	return extraProps;
}

addFilter(
	'blocks.getSaveContent.extraProps',
	'mon-projet/paragraphe-props',
	ajouterProps
);
```

Ce dernier filtre s'exécute au moment où le bloc génère son HTML final, côté `save()`. Il permet d'ajouter des attributs HTML (classe, `data-*`) sans réécrire la fonction `save` du bloc d'origine, qui reste celle fournie par le cœur de WordPress.

## Trois précautions à prendre

- Toujours filtrer par nom de bloc explicite : un filtre non ciblé s'applique à des dizaines de blocs, natifs et tiers confondus, avec des effets de bord difficiles à tracer.
- Charger ce script uniquement dans l'éditeur (`enqueue_block_editor_assets`), jamais côté front, sous peine de tenter d'exécuter du code React inutilement.
- Vérifier après chaque montée de version majeure de WordPress que les noms de filtres n'ont pas évolué : ils sont stables dans le temps, mais pas garantis figés indéfiniment.

> Sur un projet avec plusieurs dizaines de blocs Paragraphe et Titre existants dans le contenu, un filtre JavaScript bien ciblé évite une migration de contenu que la création d'un bloc de remplacement aurait rendue obligatoire.

## En résumé

Ces trois filtres suffisent à couvrir la quasi-totalité des besoins d'extension d'un bloc natif : déclaration de l'attribut, interface de réglage, et rendu final. Cette approche reste la plus légère dès que le besoin se limite à ajouter une option à un bloc existant, plutôt que de construire un bloc entièrement nouveau.
