# Un formulaire multi-étapes Gravity Forms recréé en React sans perdre la logique

> Reproduire fidèlement en React les règles d'affichage conditionnel d'un formulaire Gravity Forms complexe, en s'appuyant sur le schéma exposé par l'API REST.

- Auteur : Clément Hadrot
- Publié le : 2024-04-08
- Mis à jour le : 2024-04-08
- Catégorie : Headless &amp; API
- URL : https://wpmoderne.dev.wordpress-developpement.fr/headless/formulaire-multi-etapes-gravity-forms-react-logique/

## L’essentiel

- Le schéma exposé par l'API REST de Gravity Forms contient déjà toutes les règles conditionnelles
- Un moteur générique interprète ces règles plutôt que de les recoder à la main champ par champ
- La soumission finale doit repasser par l'endpoint natif pour conserver les notifications et intégrations existantes

Le formulaire de demande de devis d'un cabinet de conseil en assurance comptait quatorze champs répartis sur quatre étapes, avec pas moins de six règles d'affichage conditionnel : le choix du profil (particulier ou entreprise) faisait apparaître ou disparaître des blocs entiers de champs, certains champs devenaient obligatoires selon une réponse précédente, et une étape entière était sautée si le visiteur cochait « je suis déjà client ». Le tout géré depuis des années par l'éditeur visuel de Gravity Forms, entretenu par une personne non technique côté cabinet.

Le projet de refonte prévoyait un nouveau front Next.js, plus rapide et plus soigné visuellement. La question posée en amont était simple à formuler mais redoutable à réaliser : fallait-il recoder ce formulaire à la main en React, au risque de désynchroniser silencieusement la logique du nouveau formulaire de celle configurée dans Gravity Forms, ou existait-il un moyen de continuer à piloter cette logique depuis l'éditeur existant ?

## Le schéma exposé par l'API REST de Gravity Forms

Gravity Forms, avec son extension officielle d'API REST activée, expose l'intégralité de la structure d'un formulaire via l'endpoint `/gf/v2/forms/{id}`, incluant non seulement la liste des champs et leurs types, mais aussi le tableau `conditionalLogic` associé à chaque champ ou à chaque page, qui décrit précisément quelle règle déclenche l'affichage ou le masquage.

```
{
  "id": 12,
  "conditionalLogic": {
    "actionType": "show",
    "logicType": "all",
    "rules": [
      { "fieldId": 3, "operator": "is", "value": "entreprise" }
    ]
  }
}
```

Cette structure, déjà pensée pour être interprétée de façon générique par le moteur JavaScript natif de Gravity Forms côté WordPress, pouvait donc, en théorie, être réinterprétée par un moteur équivalent écrit côté React, sans jamais recopier la logique à la main.

## Construire un moteur d'interprétation plutôt qu'un formulaire codé en dur

La décision structurante du projet a été de refuser catégoriquement d'écrire un composant React spécifique à ce formulaire précis. À la place, un moteur générique a été développé, capable d'interpréter n'importe quel schéma Gravity Forms respectant cette structure de règles conditionnelles.

> L'essentiel à retenir : Le schéma exposé par l'API REST de Gravity Forms contient déjà toutes les règles conditionnelles ; Un moteur générique interprète ces règles plutôt que de les recoder à la main champ par champ ; La soumission finale doit repasser par l'endpoint natif pour conserver les notifications et intégrations existantes

```
function evaluerRegle(rule, valeurs) {
  const valeurChamp = valeurs[rule.fieldId];
  switch (rule.operator) {
    case 'is':
      return valeurChamp === rule.value;
    case 'isnot':
      return valeurChamp !== rule.value;
    case 'contains':
      return String(valeurChamp || '').includes(rule.value);
    default:
      return false;
  }
}

function champEstVisible(champ, valeurs) {
  const logique = champ.conditionalLogic;
  if (!logique) return true;
  const resultats = logique.rules.map((r) => evaluerRegle(r, valeurs));
  const correspond = logique.logicType === 'all'
    ? resultats.every(Boolean)
    : resultats.some(Boolean);
  return logique.actionType === 'show' ? correspond : !correspond;
}
```

Ce moteur, testé unitairement contre une dizaine de combinaisons de règles avant même d'être branché au vrai formulaire, a permis de valider la logique conditionnelle indépendamment du rendu visuel, ce qui a considérablement accéléré la détection d'écarts avec le comportement natif observé dans WordPress.

### Le cas des étapes entières conditionnelles

Le saut d'étape complet pour les clients existants reposait sur une règle attachée non pas à un champ mais à une page entière du formulaire (`pageConditionalLogic`). Le moteur générique a été étendu pour évaluer ce même type de règle au niveau de la navigation entre étapes, en réutilisant exactement la fonction `evaluerRegle` déjà écrite pour les champs, sans dupliquer la logique d'évaluation.

## La soumission : ne pas réinventer ce qui existe déjà

Un point important, souvent négligé sur ce type de projet : la tentation de soumettre les données directement en base de données via un endpoint personnalisé, pour « simplifier », aurait fait perdre tout le travail de configuration existant côté Gravity Forms : notifications par e-mail conditionnelles, intégration avec l'outil de CRM du cabinet, champs calculés côté serveur. La soumission finale du formulaire React continue donc de passer par l'endpoint natif `/gf/v2/forms/{id}/submissions`, avec les données collectées côté React reformatées au format attendu par cet endpoint.

```
await fetch(`${API_URL}/gf/v2/forms/12/submissions`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ input_values: valeursCollectees }),
});
```

## Ce que cette approche a permis

- L'équipe côté cabinet continue de modifier les règles conditionnelles depuis l'éditeur visuel Gravity Forms, sans intervention développeur, et le formulaire React se met à jour automatiquement à la prochaine requête.
- Un changement de règle testé en environnement de préproduction WordPress est immédiatement visible côté front, sans déploiement de code, ce qui a rassuré une équipe habituée à son ancienne autonomie.
- Le moteur générique, une fois écrit, a pu être réutilisé sur deux autres formulaires du même client sans modification, uniquement en changeant l'identifiant de formulaire interrogé.

> Reconstruire un formulaire complexe en React ne veut pas dire recopier sa logique à la main : cela veut dire trouver la structure de données qui décrit cette logique, puis écrire un interpréteur générique pour elle.

## En résumé

La difficulté de ce projet n'était pas de recréer visuellement un formulaire en React, un exercice classique. Elle était de préserver, sans régression, une logique métier fine accumulée sur plusieurs années dans l'éditeur visuel de Gravity Forms. La bonne décision a été de refuser le confort apparent du codage en dur au profit d'un moteur d'interprétation générique du schéma existant, un choix plus coûteux à écrire au départ mais infiniment plus sûr à maintenir dans la durée.
