# Draggable et le glisser-déposer d’un bloc : ce qui se joue en coulisses

> Réordonner deux blocs d'un glisser-déposer semble instantané. Derrière ce geste simple, plusieurs composants coopèrent pour recalculer la position sans jamais toucher au DOM directement.

- Auteur : WordPress Développement
- Publié le : 2021-10-07
- Mis à jour le : 2021-10-07
- Catégorie : Blocs Gutenberg
- URL : https://www.wpmoderne.fr/blocs/draggable-glisser-deposer-bloc-coulisses/

## L’essentiel

- Le composant Draggable gère la capture du geste, pas le positionnement final
- Le calcul de la nouvelle position passe par le magasin de données, pas par le DOM
- Un indicateur visuel distinct signale la position d'insertion prévue

Le glisser-déposer d'un bloc dans l'éditeur donne une impression de simplicité trompeuse : on saisit un bloc, on le déplace, il se réinsère ailleurs. Derrière ce geste, plusieurs composants distincts du paquet `@wordpress/block-editor` coopèrent, sans qu'aucun d'eux ne manipule directement le DOM pour repositionner le contenu final.

Comprendre cette mécanique aide à diagnostiquer les rares bugs de réordonnancement, et surtout à savoir où intervenir si l'on souhaite personnaliser ce comportement pour un bloc composite maison.

## Le rôle du composant Draggable

Le composant `Draggable`, exposé par `@wordpress/components`, se limite à capturer les événements natifs du navigateur liés au glisser (`dragstart`, `drag`, `dragend`) et à exposer des coordonnées de position en temps réel via une fonction de rendu enfant :

```
import { Draggable } from '@wordpress/components';

<Draggable elementId="mon-bloc" transferData={ { blockId } }>
    { ( { onDraggableStart, onDraggableEnd } ) => (
        <div
            draggable
            onDragStart={ onDraggableStart }
            onDragEnd={ onDraggableEnd }
        >
            Poignée de déplacement
        </div>
    ) }
</Draggable>
```

`Draggable` ne sait rien de la structure de blocs : il transporte simplement une donnée (`transferData`) associée au geste, ici l'identifiant du bloc concerné. La logique de réordonnancement réelle se trouve ailleurs.

## Le calcul de position via le magasin de données

> L'essentiel à retenir : Le composant Draggable gère la capture du geste, pas le positionnement final ; Le calcul de la nouvelle position passe par le magasin de données, pas par le DOM ; Un indicateur visuel distinct signale la position d'insertion prévue

Pendant le déplacement, une zone de dépôt (généralement un composant interne lié à `BlockListBlock`) calcule en continu, à partir de la position du curseur, où le bloc déplacé devrait s'insérer. Ce calcul ne modifie rien tant que le geste n'est pas terminé : il ne fait qu'afficher un indicateur visuel, une ligne fine qui matérialise le point d'insertion prévu.

Ce n'est qu'au relâchement du bouton (`dragend`) que l'action réelle est déclenchée, via le magasin de données `core/block-editor` et sa fonction `moveBlockToPosition` :

```
import { useDispatch } from '@wordpress/data';

const { moveBlockToPosition } = useDispatch( 'core/block-editor' );

moveBlockToPosition( clientId, fromRootClientId, toRootClientId, nouvelIndex );
```

Cette séparation entre affichage temporaire (l'indicateur de position) et action définitive (la mutation du magasin de données) explique pourquoi le glisser-déposer semble fluide : aucune structure de blocs n'est réellement modifiée tant que le geste est en cours, seul l'affichage change.

## Pourquoi cette séparation compte pour un bloc composite

- Un bloc parent qui souhaite personnaliser l'ordre autorisé de ses enfants (via `InnerBlocks`) ne doit pas intercepter les événements natifs du navigateur : il doit s'appuyer sur les mêmes fonctions du magasin de données que l'éditeur utilise en interne.
- Le composant `Draggable` reste un outil bas niveau : la plupart des blocs n'ont jamais besoin de l'utiliser directement, l'éditeur gérant déjà le glisser-déposer par défaut pour tout bloc enregistré normalement.
- Un bloc qui refuse certaines réorganisations le fait via `templateLock` ou `allowedBlocks`, jamais en interceptant les événements de glisser eux-mêmes.

## Un cas où comprendre ce mécanisme aide vraiment

Un bloc personnalisé qui affiche un aperçu complexe (une carte, un graphique) peut parfois capturer les événements de la souris avant qu'ils n'atteignent la poignée de déplacement de l'éditeur, rendant le bloc impossible à réordonner par glisser-déposer. Le diagnostic consiste alors à vérifier si un gestionnaire d'événement du bloc (souvent lié à une bibliothèque tierce comme une carte interactive) intercepte `mousedown` sur toute la surface du bloc, empêchant la poignée native de l'éditeur de fonctionner correctement.

> Sur les blocs qui embarquent une bibliothèque tierce interactive (carte, graphique, éditeur riche), on isole systématiquement la zone interactive avec un conteneur dédié, pour laisser la poignée de déplacement de l'éditeur totalement libre en dehors de cette zone.

## En résumé

Le glisser-déposer d'un bloc repose sur une séparation nette entre la capture du geste (via `Draggable` et les événements natifs du navigateur) et la mutation réelle de la structure (via le magasin de données `core/block-editor`). Cette architecture explique à la fois la fluidité perçue par le rédacteur et les rares cas où un bloc composite doit être conçu avec soin pour ne pas interférer avec ce mécanisme.
