API de JavaScript de Flow para formularios de WordPress
Flow expone su interfaz de ejecución en el navegador mediante el objeto global de WP Suite:
globalThis.WpSuite.plugins.flowglobalThis.WpSuite.plugins.flow.features
Utilidades de preparación
Al igual que otros plugins de WP Suite, Flow admite utilidades de preparación en tiempo de ejecución como:
onReady(cb)availability()
También puede escuchar los eventos de preparación y error emitidos en la página:
wpsuite:flow:readywpsuite:flow:error
Ejemplo:
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);
});
Acceso al almacén
Flow expone un almacén creado de forma diferida mediante:
WpSuite.plugins.flow.features.store
Resulta útil para integraciones avanzadas que necesitan acceder al estado o la configuración de Flow en tiempo de ejecución.
API de modales
Flow también expone un controlador de modales en el DOM ligero mediante WpSuite.plugins.flow.modals.
Métodos 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)
Eventos del ciclo de vida admitidos:
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
Los controladores de acciones registrados mediante registerAction(actionName, handler) pueden ser asíncronos. El entorno de ejecución modal espera la promesa devuelta, mantiene abierto el modal durante la espera, lo pone en estado ocupado, desactiva los activadores de acciones modales estándar y marca el elemento activador en ejecución con data-wps-flow-pending="true" y aria-busy="true". Este marcador pendiente es deliberadamente genérico, por lo que funciona tanto con bloques Botón del núcleo como con marcado de botones personalizado.
Si un controlador asíncrono devuelve false, se omite el cierre automático y el modal permanece abierto. En las rutas de cierre que descartan el modal, como el botón de cierre integrado, los clics en el fondo, Escape o las llamadas de cierre programáticas, el entorno también emite wps-flow-modal:dismiss.
Ejemplo: abrir un modal de Flow desde un botón vecino de Gutenberg, cerrarlo desde otro botón de Gutenberg dentro del modal y escuchar el evento de cierre:
- En el inspector del bloque Modal de Flow, establece
modalIdennewsletter-preferences. - Añada un bloque Botón del núcleo junto al modal y establezca
Advanced -> Additional CSS class(es)enwps-flow-modal-open--newsletter-preferences. - Añada otro bloque Botón del núcleo dentro del contenido modal y establezca
Advanced -> Additional CSS class(es)enwps-flow-modal-close. - Escuche
wps-flow-modal:closeendocument.
WordPress aplica esas clases personalizadas al envoltorio .wp-block-button renderizado, por lo que el entorno de ejecución resuelve el activador desde el enlace o botón interno pulsado hasta ese envoltorio.
<!-- 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>
Para un bloque Botón del núcleo, la ruta mediante clases CSS suele ser la integración más sencilla, porque el entorno de ejecución ya delega los clics de .wps-flow-modal-open--{modalId} y .wps-flow-modal-close. Un botón .wps-flow-modal-close cierra el modal de Flow más cercano y emite wps-flow-modal:close con detail.returnValue === "close".
Elementos que abren galerías y tienen en cuenta el modal
wps-flow-modal:open incluye el triggerElement que abrió el diálogo, y WpSuite.plugins.flow.modals.open(modalId, { triggerElement }) acepta la misma entrada para aperturas programáticas. El bloque Galería de Flow usa ese elemento de apertura para resolver estas indicaciones opcionales:
wps-flow-gallery-target--{galleryId}odata-wps-flow-gallery-target="{galleryId}"wps-flow-gallery-index--Nodata-wps-flow-gallery-index="N"
Esto permite que un bloque Imagen o Botón del núcleo vecino abra un modal y muestre una imagen concreta de la galería. Si el modal contiene una sola Galería de Flow, se puede omitir la indicación de destino y basta con el índice.
<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,
});
Valores predeterminados de campos limitados al formulario
El núcleo de Flow también expone métodos auxiliares en WpSuite.plugins.flow para los valores predeterminados de campos limitados al formulario:
setFormFieldDefaultValue(formId, fieldName, value)setFormFieldDefaultValues(formId, values)clearFormFieldDefaultValues(formId)getFormFieldDefaultValue(formId, fieldName)getFormFieldDefaultValues(formId)
Cada utilidad devuelve una Promise porque Flow espera a que su almacén interno esté disponible antes de leer o escribir valores.
Ejemplo:
await globalThis.WpSuite.plugins.flow.setFormFieldDefaultValues("newsletter-footer", {
email: "user@example.com",
utm_source: "spring-campaign",
});
Si prefiere trabajar directamente con el almacén, usa las mismas acciones mediante features.store y 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");
Estas API escriben valores predeterminados limitados al formulario en el almacén compartido de Flow. Los formularios de Flow renderizados resuelven y aplican esos valores mediante formId.
Interpolación de cadenas en tiempo de ejecución
Algunos ajustes de cadenas de Flow en tiempo de ejecución admiten interpolación de tokens. En la práctica, Flow sustituye los marcadores {{...}} por valores del contexto de la página actual antes de usar la cadena.
Resulta útil para ajustes como un endpointPath por formulario o el apiEndpoint de un campo de opciones respaldado por una API, cuando la URL final depende de la página actual, la cadena de consulta, variables globales de la página contenedora o los valores actuales del formulario.
Los campos de opciones respaldados por una API también pueden derivar el estado de selección inicial de cada elemento de respuesta. Use apiSelectedPath para leer un indicador o campo de estado de cada elemento y, opcionalmente, apiSelectedValue cuando el elemento deba considerarse seleccionado solo para un valor concreto como SUBSCRIBED. Resulta especialmente útil para checkbox-group, y también se aplica a los campos select, radio y tags.
Para envíos de formularios personalizados, la URL del punto de conexión puede combinarse con un endpointMethod de GET, POST, PUT o PATCH. Si no se configura ningún método, Flow usa POST. Cuando se selecciona GET, Flow envía los valores serializados de los campos como parámetros de consulta de la URL en vez de como un cuerpo de solicitud JSON. También puede adjuntar encabezados adicionales de solicitud del navegador mediante endpointHeaders (almacenados como una cadena de objeto JSON en los atributos del bloque); Flow los combina con el encabezado de solicitud de reCAPTCHA existente cuando corresponde. Los valores de los encabezados admiten los mismos tokens de interpolación en tiempo de ejecución que endpointPath, pero se resuelven como cadenas simples en lugar de segmentos de ruta codificados para URL.
Cuando se usan tokens de ejecución en endpointPath o en el apiEndpoint de un campo respaldado por API, Flow codifica para URL los valores dinámicos de los campos y de la cadena de consulta antes de insertarlos en la URL final.
Las familias de tokens admitidas son:
{{email}},{{fullName}},{{message}}, etc., para los valores actuales de los campos del formulario por nombre de campo{{query.foo}}— valores de la cadena de consulta 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., como abreviatura del objeto globalWpSuite.*{{global.MyApp.config.formsBaseUrl}}para cualquier otro valor primitivo accesible englobalThis{{field.email}},{{field.fullName}}, etc., como alias explícito de los valores actuales de los campos del formulario
Ejemplos:
{{location.origin}}/contact
https://api.example.com/forms?source={{location.pathname}}
{{wpsuite.apiBaseUrl}}/contact
{{global.MyApp.forms.submitUrl}}
{{wpsuite.contactApiBaseUrl}}/{{email}}
Restricciones importantes:
- La interpolación no es ejecución arbitraria de JavaScript. Solo lee valores de contextos de ejecución conocidos o de rutas de propiedades en
globalThis. - No se admiten llamadas a funciones, expresiones ni condicionales como
foo ? bar : baz. - Para
global.*ywpsuite.*, el valor debe existir ya en la página como un valor primitivo (string,numberoboolean) cuando Flow resuelva el ajuste. - Los tokens de valores actuales de los campos solo están disponibles en interfaces de ejecución que ya tienen acceso al estado del formulario, como los campos renderizados y los cargadores de opciones respaldados por API.
Decisión de capacidades
En integraciones empaquetadas, Flow también expone funciones auxiliares como waitForFlowReady(), getStore(), decideCapability() y resolveBackend() mediante el módulo del núcleo de Flow. Resultan útiles cuando necesita esperar a la inicialización o decidir si el sitio actual puede usar funciones que conocen el backend.
Eventos de formulario en tiempo de ejecución
Los formularios de Flow renderizados emiten eventos CustomEvent con propagación para las acciones importantes del entorno de ejecución. Puede escucharlos en el elemento contenedor del formulario o en el nivel de document, porque los eventos se propagan y atraviesan el límite de la raíz de sombra.
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);
});
Los eventos actuales incluyen:
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
Cada evento específico también emite un evento genérico smartcloud-flow:state-change cuyo campo detail.event contiene el nombre del evento original.
Entre los campos habituales de detail se incluyen:
formIdactionsubmissionIdstatussuggestionId- metadatos del asistente como
wizardPath,stepIndex,stepTitleytotalVisibleSteps
Para los errores de carga de campos respaldados por API, detail también puede incluir fieldName, fieldType, requestMethod, errorType, message, status y responseText.
Ejemplo: gestionar un error de opciones respaldadas por API desde el JavaScript de la página contenedora:
<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>
Use detail.message en la interfaz visible para el usuario. Trata detail.responseText como datos de diagnóstico o depuración, no como algo que deba mostrarse directamente a los usuarios finales.
Esta capa de eventos es el punto de integración recomendado cuando una aplicación externa necesita analítica, seguimiento de conversiones, redirecciones personalizadas o reacciones de la interfaz de la página contenedora.
