API JavaScript Flow pour les formulaires WordPress
Flow expose sa surface runtime navigateur sous le global WP Suite :
globalThis.WpSuite.plugins.flowglobalThis.WpSuite.plugins.flow.features
Aides à la disponibilité
Comme les autres plugins WP Suite, Flow prend en charge des aides à la disponibilité au runtime telles que :
onReady(cb)availability()
Vous pouvez aussi écouter les événements de disponibilité/erreur émis sur la page :
wpsuite:flow:readywpsuite:flow:error
Exemple :
window.addEventListener("wpsuite:flow:ready", () => {
const flow = globalThis.WpSuite?.plugins?.flow;
console.log("Flow is ready", flow?.status);
});
window.addEventListener("wpsuite:flow:error", (event) => {
console.error("Flow failed to initialize", event.detail);
});
Accès au store
Flow expose un store créé à la demande via :
WpSuite.plugins.flow.features.store
C’est utile pour les intégrations avancées qui ont besoin d’accéder à l’état runtime de Flow ou à sa configuration.
API des modales
Flow expose aussi un contrôleur de modale en DOM léger sous WpSuite.plugins.flow.modals.
Méthodes disponibles :
register(modalElement, options?)unregister(modalOrId)open(modalId, options?)close(modalId, returnValue?)toggle(modalId, options?)closeAll(returnValue?)isOpen(modalId)get(modalId)registerAction(actionName, handler)unregisterAction(actionName)
Événements de cycle de vie pris en charge :
wps-flow-modal:before-openwps-flow-modal:openwps-flow-modal:before-closewps-flow-modal:closewps-flow-modal:okwps-flow-modal:cancelwps-flow-modal:dismisswps-flow-modal:error
Les gestionnaires d’action enregistrés via registerAction(actionName, handler) peuvent être asynchrones. Le runtime de la modale attend la promesse renvoyée, laisse la modale ouverte pendant l’attente, passe la modale en état occupé, désactive les déclencheurs d’action standards de la modale et marque l’élément déclencheur actuellement en cours avec data-wps-flow-pending="true" et aria-busy="true". Ce marqueur pending est volontairement générique, afin de fonctionner aussi bien avec les blocs Button natifs qu’avec un balisage de bouton personnalisé.
Si un gestionnaire asynchrone renvoie false, la fermeture automatique est ignorée et la modale reste ouverte. Pour les chemins de fermeture de type dismiss comme le bouton de fermeture intégré, les clics sur l’arrière-plan, Escape ou les appels de fermeture programmatiques, le runtime émet aussi wps-flow-modal:dismiss.
Exemple : ouvrir une modale Flow depuis un bouton Gutenberg voisin, la fermer depuis un autre bouton Gutenberg à l’intérieur de la modale et écouter l’événement de fermeture :
- Dans l’inspecteur du bloc Flow Modal, définissez
modalIdsurnewsletter-preferences. - Ajoutez un bloc Button natif à côté de la modale et définissez
Advanced -> Additional CSS class(es)surwps-flow-modal-open--newsletter-preferences. - Ajoutez un autre bloc Button natif à l’intérieur du contenu de la modale et définissez
Advanced -> Additional CSS class(es)surwps-flow-modal-close. - Écoutez
wps-flow-modal:closesurdocument.
WordPress applique ces classes personnalisées sur le wrapper .wp-block-button rendu, de sorte que le runtime remonte du lien ou du bouton interne cliqué vers ce wrapper.
<!-- Neighboring core/button block -->
<div class="wp-block-button wps-flow-modal-open--newsletter-preferences">
<a class="wp-block-button__link wp-element-button">
Open preferences
</a>
</div>
<!-- Inside the Flow Modal block -->
<div class="wp-block-button wps-flow-modal-close">
<a class="wp-block-button__link wp-element-button">
Close popup
</a>
</div>
<script>
document.addEventListener("wps-flow-modal:close", (event) => {
const detail = event.detail ?? {};
if (detail.modalId !== "newsletter-preferences") {
return;
}
console.log("Flow modal closed", {
modalId: detail.modalId,
returnValue: detail.returnValue,
});
// Example: reset host-page UI or fire analytics here.
});
</script>
Pour un bloc Button natif, la route par classe CSS est généralement l’intégration la plus simple, car le runtime délègue déjà les clics pour .wps-flow-modal-open--{modalId} et .wps-flow-modal-close. Un bouton .wps-flow-modal-close ferme la modale Flow la plus proche et émet wps-flow-modal:close avec detail.returnValue === "close".
Ouvreurs de galerie sensibles à la modale
wps-flow-modal:open inclut triggerElement, qui a ouvert la boîte de dialogue, et WpSuite.plugins.flow.modals.open(modalId, { triggerElement }) accepte la même entrée pour les ouvertures programmatiques. Le bloc Flow Gallery utilise cet élément déclencheur pour résoudre ces indices facultatifs :
wps-flow-gallery-target--{galleryId}oudata-wps-flow-gallery-target="{galleryId}"wps-flow-gallery-index--Noudata-wps-flow-gallery-index="N"
Cela permet à un bloc Image natif ou Button natif voisin d’ouvrir une modale et d’atterrir sur une image de galerie précise. Si la modale ne contient qu’une seule Flow Gallery, l’indice de cible peut être omis et l’index seul suffit.
<div class="wp-block-image wps-flow-modal-open--product-lightbox wps-flow-gallery-target--product-gallery wps-flow-gallery-index--2">
<figure class="wp-block-image size-large">
<img src="/images/product-side.jpg" alt="Product side view" />
</figure>
</div>
const triggerElement = document.querySelector(".hero-product-image");
globalThis.WpSuite.plugins.flow.modals.open("product-lightbox", {
triggerElement,
});
Valeurs par défaut de champs limitées au formulaire
Le cœur de Flow expose aussi des méthodes d’aide sur WpSuite.plugins.flow pour les valeurs par défaut de champs limitées au formulaire :
setFormFieldDefaultValue(formId, fieldName, value)setFormFieldDefaultValues(formId, values)clearFormFieldDefaultValues(formId)getFormFieldDefaultValue(formId, fieldName)getFormFieldDefaultValues(formId)
Chaque aide renvoie une Promise, car Flow attend son store interne avant de lire ou d’écrire des valeurs.
Exemple :
await globalThis.WpSuite.plugins.flow.setFormFieldDefaultValues("newsletter-footer", {
email: "user@example.com",
utm_source: "spring-campaign",
});
Si vous préférez travailler directement avec le store, utilisez les mêmes actions via features.store et wp.data.dispatch(...) :
const store = await globalThis.WpSuite.plugins.flow.features.store;
const actions = globalThis.wp.data.dispatch(store);
actions.setFormFieldDefaultValue("newsletter-footer", "email", "user@example.com");
Ces API écrivent des valeurs par défaut limitées au formulaire dans le store Flow partagé. Les formulaires Flow rendus résolvent et appliquent désormais ces valeurs par formId.
Interpolation de chaînes au runtime
Certains paramètres de chaînes runtime Flow prennent en charge l’interpolation de jetons. En pratique, cela signifie que Flow remplace les espaces réservés {{...}} par des valeurs du contexte de page courant avant d’utiliser la chaîne.
C’est utile pour des paramètres tels qu’un endpointPath par formulaire ou le apiEndpoint d’un champ d’options alimenté par une API lorsque l’URL finale dépend de la page courante, de la chaîne de requête, des globals de la page hôte ou des valeurs du formulaire courant.
Les champs d’options alimentés par API peuvent aussi dériver l’état initial de sélection à partir de chaque élément de réponse. Utilisez apiSelectedPath pour lire un indicateur ou un champ d’état par élément, et éventuellement apiSelectedValue lorsque l’élément ne doit compter comme sélectionné que pour une valeur spécifique telle que SUBSCRIBED. C’est particulièrement utile pour checkbox-group, et cela s’applique aussi aux champs select, radio et tags.
Pour les soumissions de formulaire personnalisées, l’URL du point de terminaison peut être associée à un endpointMethod de GET, POST, PUT ou PATCH. Si aucune méthode n’est configurée, Flow utilise POST. Lorsque GET est sélectionné, Flow envoie les valeurs de champ sérialisées sous forme de paramètres de requête d’URL au lieu d’un corps de requête JSON. Vous pouvez aussi joindre des en-têtes de requête côté navigateur via endpointHeaders (stocké comme une chaîne JSON d’objet dans les attributs du bloc) ; Flow les fusionne avec l’en-tête de requête reCAPTCHA existant lorsqu’il est présent. Les valeurs d’en-tête prennent en charge les mêmes jetons d’interpolation runtime que endpointPath, mais elles sont résolues en chaînes simples plutôt qu’en segments de chemin encodés dans l’URL.
Lorsque des jetons runtime sont utilisés dans endpointPath ou dans le apiEndpoint d’un champ alimenté par API, Flow encode les valeurs dynamiques des champs et des jetons de chaîne de requête avant de les insérer dans l’URL finale.
Les familles de jetons prises en charge sont :
{{email}},{{fullName}},{{message}}, etc. pour les valeurs des champs du formulaire courant par nom de champ{{query.foo}}— valeurs de chaîne de requête issues dewindow.location.search{{location.href}},{{location.origin}},{{location.pathname}},{{location.search}},{{location.hash}}, etc.{{wp.postId}},{{wp.postSlug}},{{wp.postType}},{{wp.postTitle}},{{wp.postUrl}}{{wpsuite.apiBaseUrl}},{{wpsuite.siteSettings.siteId}}, etc. comme raccourci pour l’objet globalWpSuite.*{{global.MyApp.config.formsBaseUrl}}pour toute autre valeur primitive accessible surglobalThis{{field.email}},{{field.fullName}}, etc. comme alias explicite des valeurs de champ du formulaire courant
Exemples :
{{location.origin}}/contact
https://api.example.com/forms?source={{location.pathname}}
{{wpsuite.apiBaseUrl}}/contact
{{global.MyApp.forms.submitUrl}}
{{wpsuite.contactApiBaseUrl}}/{{email}}
Contraintes importantes :
- L’interpolation n’est pas une exécution JavaScript arbitraire. Elle lit seulement des valeurs provenant de contextes runtime connus ou de chemins de propriété sur
globalThis. - Les appels de fonction, expressions et conditions comme
foo ? bar : bazne sont pas pris en charge. - Pour
global.*etwpsuite.*, la valeur doit déjà exister sur la page sous forme de primitive (string,numberouboolean) lorsque Flow résout le paramètre. - Les jetons de valeur de champ du formulaire courant ne sont disponibles que dans les surfaces runtime qui ont déjà accès à l’état du formulaire, comme les champs de formulaire rendus et les chargeurs d’options alimentés par API.
Décision de capacité
Dans les intégrations packagées, Flow expose aussi des fonctions d’aide comme waitForFlowReady(), getStore(), decideCapability() et resolveBackend() via le module cœur Flow. Ces aides sont utiles lorsque vous devez attendre l’initialisation ou décider si le site courant peut utiliser des fonctionnalités conscientes du backend.
Événements runtime du formulaire
Les formulaires Flow rendus émettent des CustomEvent en propagation pour les actions runtime importantes. Vous pouvez écouter sur l’élément hôte du formulaire ou au niveau de document, car les événements se propagent et traversent la frontière du shadow DOM.
document.addEventListener("smartcloud-flow:submit-success", (event) => {
console.log("Flow submit success", event.detail);
});
document.addEventListener("smartcloud-flow:wizard-step-change", (event) => {
console.log("Wizard moved", event.detail);
});
Les événements actuels incluent :
smartcloud-flow:draft-savedsmartcloud-flow:draft-loadedsmartcloud-flow:draft-deletedsmartcloud-flow:ai-suggestion-acceptedsmartcloud-flow:ai-suggestions-rejectedsmartcloud-flow:submit-after-ai-acceptedsmartcloud-flow:submit-successsmartcloud-flow:success-state-shownsmartcloud-flow:wizard-step-changesmartcloud-flow:return-to-formsmartcloud-flow:options-request-errorsmartcloud-flow:error
Chaque événement spécifique émet aussi un événement générique smartcloud-flow:state-change dont le champ detail.event contient le nom d’événement d’origine.
Les champs detail courants incluent :
formIdactionsubmissionIdstatussuggestionId- des métadonnées du wizard telles que
wizardPath,stepIndex,stepTitleettotalVisibleSteps
Pour les erreurs de chargement de champs alimentés par API, detail peut aussi inclure fieldName, fieldType, requestMethod, errorType, message, status et responseText.
Exemple : gérer une erreur d’options alimentées par API depuis le JavaScript de la page hôte :
<div id="preferences-api-error" hidden></div>
<script>
const errorBox = document.getElementById("preferences-api-error");
document.addEventListener("smartcloud-flow:options-request-error", (event) => {
const detail = event.detail ?? {};
if (detail.formId && detail.formId !== "preferences-form") {
return;
}
const message =
typeof detail.message === "string" && detail.message.trim()
? detail.message.trim()
: "Unable to load options right now.";
if (errorBox) {
errorBox.textContent = message;
errorBox.hidden = false;
}
console.warn("Flow options request error", {
formId: detail.formId,
fieldName: detail.fieldName,
status: detail.status,
errorType: detail.errorType,
responseText: detail.responseText,
});
});
document.addEventListener("smartcloud-flow:submit-success", () => {
if (errorBox) {
errorBox.hidden = true;
errorBox.textContent = "";
}
});
</script>
Utilisez detail.message pour l’interface visible par l’utilisateur. Traitez detail.responseText comme une donnée de diagnostic/débogage plutôt que comme quelque chose à afficher directement aux utilisateurs finaux.
Cette couche d’événements est le point d’intégration recommandé lorsqu’une application externe a besoin d’analytique, de suivi des conversions, de redirections personnalisées ou de réactions d’interface côté page hôte.
