Advanced

Migrating from Formie Plugin ​

Use the compatibility bridge to move existing browser integrations to @verbb/formie-browser one listener at a time. It forwards supported DOM and validator events while you update your handlers.

Use the bridge only as a migration step, then register all listeners with the formie:* event names.

What Changed ​

The main browser changes from the old bundled Formie plugin JavaScript are:

  • lifecycle and submit hooks now use canonical formie:* DOM events
  • validator lifecycle hooks now use canonical formie:validator:* events
  • the public browser API is now either the formie() helper or a client created with createFormieClient()

If your old code only listens for supported legacy event names, leave compatibility enabled while you migrate each listener to the new event surface.

Turn on Compatibility ​

Managed or Rendered Forms ​

Formie-rendered HTML inherits the plugin's compatibilityMode setting, which is enabled by default. This works with automatic startup and HTML loaded through REST or GraphQL; you do not need your own bundle or mount call. Purge cached form HTML after changing the setting.

For standalone HTML that Formie does not render, enable compatibility on the root:

html
<form data-formie data-formie-form data-formie-compatibility="true">
  ...
</form>

Your Own Bundle ​

If you mount with the package directly, the rendered form still supplies the default. Pass an explicit compatibility option to override it:

ts
import { createFormieClient } from '@verbb/formie-browser';

const formie = createFormieClient();
const root = document.querySelector('[data-formie-form]');

if (root instanceof HTMLElement) {
  await formie.mount(root, {
    mode: 'server-rendered',
    compatibility: true,
  });
}

You can also opt into only part of the bridge:

ts
await formie.mount(root, {
  mode: 'server-rendered',
  compatibility: {
    legacyDomEvents: true,
    legacyValidatorEvents: false,
  },
});

Event Mapping ​

These legacy DOM events can be bridged during migration:

Legacy eventCanonical eventNotes
onFormieLoadedformie:mount:afterApproximate mapping
onFormieInitformie:mount:afterApproximate mapping
onFormieReadyformie:mount:afterSafe mapping
onAfterFormieSubmitformie:submit:resultSafe mapping
onFormieSubmitErrorformie:submit:resultSafe mapping
onFormiePageToggleformie:page:navigate:afterSafe mapping
onBeforeFormieSubmitformie:submit:beforeApproximate mapping
onFormieValidateformie:stage:validate:beforeApproximate mapping
onAfterFormieValidateformie:stage:validate:afterApproximate mapping
onFormieSubmitformie:submit:afterApproximate mapping

These validator events can be bridged too:

Legacy eventCanonical event
formieValidatorInitializedformie:validator:ready
formieValidatorDestroyedformie:validator:destroy
formieValidatorShowErrorformie:validator:show-error
formieValidatorClearErrorformie:validator:clear-error

Approximate mappings do not preserve every timing or cancellation behaviour. In particular, onFormieLoaded and onFormieInit fire for each mounted form, legacy events do not forward preventDefault() to the workflow, and onFormieThemeReady is not bridged.

  1. Leave the plugin's compatibility mode enabled, or enable the bridge for standalone HTML.
  2. Replace old event listeners with the canonical formie:* or formie:validator:* names.
  3. Test any submit-flow logic that relied on older event timing.
  4. Remove compatibility once the old listeners are gone.

Address Hooks ​

Older forms may still render legacy bare hooks such as [data-address1] or [data-state]. Provider modules fall back to those automatically via ADDRESS_LEGACY_SELECTORS. Use the attributes in Address Reference when updating your markup.

Last updated: Oct 15, 2026, 11:40 PM