github verbb/formie 4.0.0

3 hours ago

{warning} Before upgrading to Formie 4, review the Upgrading from v3 guide for breaking changes and required migration steps.

Added

  • Add a Formie 3 to Formie 4 migration path for existing Craft 5 projects.
  • Add direct Formie 2 to Formie 4 migration support, allowing Craft 4 projects to move to Craft 5 without upgrading through Formie 3 first.
  • Add Formie 4 Compatibility Mode, enabled by default, to bridge selected Formie 3 class aliases, event owners, custom field schema methods, field config keys, theme config keys, and legacy front-end event listeners during upgrades.
  • Add first-party framework-agnostic, browser, React, Vue, and Web Components packages for server-rendered and client-rendered forms, with REST and GraphQL transports.
  • Add headless GraphQL payment support: structured Payment field input types, payment follow-up fields on submitFormieClientForm, and BYO provider documentation. (#1375)
  • Add GraphQL Json siblings for stored rich-text content alongside existing Html fields (#865): submitActionMessageJson, errorMessageJson, instructionsJson, descriptionJson, and contentJson.
  • Add generic saveSubmission GraphQL mutation for handle-based submission saves (#1007).
  • Add developer extension APIs for schema-driven integration and notification settings, submission workflow stages and tasks, field value projections, slot tags, client modules, and programmatic form and submission factories.
  • Add Form Statuses to label form lifecycle states in the control panel (active, draft, archived), with form builder assignment, index status menu filtering, bulk actions, and project config support. Rename existing submission workflow labels to Submission Statuses, with backward-compatible class aliases. (#1471)
  • Dispatch integrations on control panel submission saves when the re-run policy includes Control panel save, including bulk status changes and other direct element saves. CP submission edit saves continue to use the submission workflow without double-triggering. (Discussion #2253)
  • Add a staged submission workflow service (SubmissionWorkflow) with preflight, validate, screen, persist, dispatch, and finalize stages.
  • Add database-backed temporary submission state, incomplete submission state, saved drafts, and resume-token handling.
  • Add multi-site support with automatic site availability via Form Group site policy, per-site content translation via sparse site overrides, portable stencil translations, and per-site required-field overrides. (#2308, #84, #2724, #2968, #2982)
  • Add a dedicated optional field-content encryption key, an Encryption settings page, key generation and status commands, resumable re-encryption, previous-key recovery, and read-only handling for unavailable encrypted values.
  • Add siteHandle request parameter support for headless form load and submit endpoints (#2286).
  • Add Cleanup service, ./craft formie/gc/run, and ./craft formie/cron/run console commands for scheduled cleanup and retention. formie/cron/run also runs due scheduled reports, with --only, --skip-gc, and --skip-reports for finer scheduling control.
  • Add Reports control panel section for saved analytical views over submissions: filters, summary counts, charts, column configuration, and on-demand export (CSV, Excel, JSON, XML, text) with configurable filename tokens. (#647)
  • Add Scheduled Reports to email a summary and export attachment from a saved report on daily or weekly schedules, with configurable file type, optional email template, recipients, and user group delivery. (#692, #2184)
  • Add Report Async Export Row Threshold setting (Settings → Submissions) to queue large report exports in the background (default 1000 rows). (#2259)
  • Add Quiz field to forms for scored questionnaires (#605). Each question supports radio buttons, checkboxes, or a dropdown; mark correct answers on static options, enable optional Weighted score for per-option points, and add Answer explanation rich text for incorrect responses. Form Behaviour → Quiz Scoring settings control pass percentage, retake restrictions (by logged-in user or IP address), and whether Ajax/client submit responses include a quizResult payload after a successful final-page submit. Scores persist in formie_submission_quiz_results for complete, non-spam submissions.
  • Add Survey field to forms with selectable presentation types: radio buttons, checkboxes, dropdown, Likert scale (#798), Rating star scale (#2282), and Rank drag-and-drop ordering (#605). Likert supports single- and multi-row layouts, optional Weighted score on static columns, and built-in predefined scale defaults. Rank fields preserve submitted order on validation re-render.
  • Add a Results tab to the form builder when a form includes Quiz or Survey fields (#605). View per-question response counts and option breakdowns, rank-weighted preference charts, Likert scoring averages when weighted scoring is enabled, and a quiz summary (attempts, average score, pass rate, pass threshold) for scored quizzes.
  • Add Checkout Mode setting to the Opayo payment integration, with Own Form (default) and Drop-in Checkout options. Drop-in Checkout renders card fields inside an Opayo-hosted iframe via sagepayCheckout, which can reduce PCI scope compared to own-form tokenisation, while reusing the existing server-side session key, transaction, and 3DS callback flow.
  • Add registered Custom Provider option sources for Dropdown, Radio, Checkboxes, and Recipients fields. Modules can register lightweight OptionSourceProviderInterface classes via OptionSources::EVENT_REGISTER_OPTION_SOURCE_PROVIDERS for local Craft data without building a full integration. See Custom option source providers. (#1421)
  • Add dynamic Brevo list assignment via field mapping. Map a form field to the Brevo List integration field to subscribe contacts to a submission-specific list, with fallback to the form’s configured list. (#2849)
  • Add Merge Multi-Option Fields setting to the Pipedrive integration. When updating an existing person (matched by email), mapped multi-option field values such as labels can be appended to existing values instead of replacing them.
  • Add a persisted metadata JSON column on submissions for submit-time request context (referrer, user agent, tracking cookies) and developer-defined custom data via form.setSubmissionMetadata(). Reference tokens such as {metadata:custom.campaignId} and {metadata:request.referrer} are supported in notifications, integrations, and PDFs. (#1379)
  • Add top-level Integrations control panel navigation for managing CRM, email marketing, element, and other payload integrations outside Settings.
  • Add site-scoped integrations that can be created and edited on production environments (allowAdminChanges = false). Existing integrations remain project-scoped and deploy via project config.
  • Add When integrations re-run settings (Integrations → Settings) with per-integration policies: once on submit (default), also when submission is edited, or custom trigger events. Integration conditions still apply. (#1429, #1724, #2591, #1970)
  • Add Use Submission User as Author to Entry element integrations, assigning the collected submission user as the entry author when Collect User is enabled on the form. (#1363)
  • HubSpot Map to Form integrations now resolve custom object objectTypeId values when submitting to HubSpot forms, including portal-specific custom objects (Enterprise). Refresh HubSpot forms after creating custom objects. (#2649)
  • Add Enable Conditions to form integration settings, allowing integrations to be triggered only when submission field and status rules match. (#447)
  • Add Integration Dispatch form settings (Integrations → Settings) to run payload integrations sequentially, choose immediate vs queued execution per integration, control notification timing relative to integrations, and expose dispatch results via {dispatch:handle:property} variables (for example {dispatch:user:url}). Dispatch variables appear in variable pickers when integration dispatch is enabled. (#2635, #1152, #2810)
  • Add durable integration and notification delivery history with encrypted diagnostics, safe retries, reconciliation tools, and support-download controls.
  • Add configurable Integration API Error Handling for Mailchimp and Campaign Monitor, classifying rate-limited and rejected payloads separately from operational failures. (#2172, #1990)
  • Add Integrations::EVENT_AFTER_TRIGGER_INTEGRATION_FAILED for handling integration failures outside the queue, and Send Email Alert for Failed Integration settings mirroring failed notification alerts. (Discussion #2579)
  • Add integration option sources, allowing integrations to opt in and expose selectable remote option lists to Dropdown, Radio and Checkboxes fields. (#512)
  • Add Mailchimp option sources for Interest Categories and Tags, using cached integration form settings and manual refresh actions from the field settings UI. (#512)
  • Add CRM integration option sources for HubSpot (forms and CRM properties), Salesforce, Zoho, and Microsoft Dynamics 365 picklists. (#512)
  • Add Salesforce Client Credentials authentication with configurable My Domain support. (#2961)
  • Add an event-based Microsoft Dynamics 365 entity registry for custom entities without requiring a custom integration subclass. (#2995)
  • Add repeater sub-field reference support with explicit row scope (first, last, index, all, count, custom row expressions) for variable tokens, notifications, conditions, and integrations. Repeater nested fields now appear once in the variable picker, with row targeting configured in the variable settings popover. (#1728, #1255, #2099, #1888, #2338)
  • Add console commands to inspect unresolved payments, reconcile gateway status, record verified outcomes and resume submission processing.
  • Add Stripe subscription Payment Limit field settings to cancel subscriptions automatically after a fixed or dynamic number of payments using Stripe subscription schedules. (#2123)
  • Add Stripe subscription Setup Fee field settings to charge a one-time fee on the first subscription invoice using Stripe invoice items. (#1767)
  • Migrate GoCardless payments from deprecated Redirect Flows to Billing Request Flows, including mandate fulfilment, one-off payment creation, and billing request webhooks. (#2552)
  • Add GoCardless recurring subscription support via Direct Debit mandate authorisation and GoCardless subscription creation after billing request fulfilment. (#2552)
  • Add Display Type settings to File Upload fields: File Input (Simple) keeps the native browser input and uploads files on form submit; Upload Manager (Advanced) adds a drag-and-drop zone with async staged uploads, progress, remove, and reorder controls via Formie’s upload endpoints. Existing forms default to File Input (Simple). (#133, #2385, Discussion #1692)
  • Add per-field Asset Data Retention settings to File Upload fields, allowing uploaded assets to be deleted after a configured duration while the submission record is kept. (#1715)
  • Add unique-value, match-field, text-limit, number-limit, email-format, blocked-domain, options-limit, and file-upload validation message overrides on supported field types. (#1475)
  • Add existing and synced fields to Group fields from the form builder, so reusable field definitions can be placed inside independent group wrappers with namespaced handles. (#2069)
  • Add form group policies for allowed submission statuses, optional per-group field palettes, and new-form default profiles (stencil, templates, form defaults). Group policies inherit from global settings; allowed submission statuses are enforced at the group level. (#2717, #2209, #863)
  • Add optional per-form reCAPTCHA Action and Minimum Score settings for score-based modes, inheriting global Spam Protection defaults when left blank. (#2167, #2804)
  • Add Settings → Synced Fields as a read-only audit page listing shared field definitions and the forms they appear on, with a View usage link from synced fields in the form builder. (#2377)
  • Add a configurable field palette for the form builder, with drag-and-drop group and field organisation, per-field enable/disable, and optional palette label overrides. Replaces the legacy Disabled Field Types settings checkboxes. (#2209)
  • Add synced-field support for stencils, preserving shared definition links when creating new forms from a stencil. (#1677, #1734)
  • Add stencil scopes so developers can ship starter forms in project config while content editors can create and manage their own stencils in the control panel. (#2814)
  • Add Form Groups for control panel organisation. (#1039, #662)
  • Add a dedicated Settings → Defaults control panel page for form, field, and notification defaults. (#863)
  • Show field handles in the form builder when the Craft user preference Show field handles in edit forms is enabled (admin users only), with a copy-to-clipboard control on hover. (#2279)
  • Show an Encrypted padlock badge on fields in the form builder when Enable Content Encryption is turned on. (#2332)
  • Add an optional Other choice for Radio fields, with a configurable label and free-text input on the front-end. (#1875)
  • Add password validation settings to the Password field: minimum length, and requirements for uppercase, lowercase, and special characters. (#1880)
  • Add a Unique User Email setting to Email Address fields, to reject email addresses already associated with a Craft user account. (#1151)
  • Add global Allowed domains email rules under Settings → Spam Protection → Email Rules. Allowlisted domains or full email addresses skip global blocked-domain and free-provider checks only; other spam screening still applies. (#2335)
  • Add craft.formie.ref() and craft.formie.refField() for building variable-picker-compatible reference tokens from Twig when overriding settings such as submitActionMessage. See Reference tokens. (#2838)
  • Add Lock Field Settings and Editor Note on the field editor Advanced tab to help content authors protect important field configuration. Locking dims field settings until Unlock is clicked for the session; notes appear in the field editor banner. (#1189)
  • Add Field Error Announcement plugin setting (Settings → Forms) to control how front-end validation and submit errors are announced to screen readers (polite, assertive, or off). Live validation while typing always uses polite announcements. (#2505)
  • Add scoped Submission Limits per form: cap all submissions for a form (closes the form when reached), submissions per IP address, or submissions per logged-in user, over configurable periods. Discussion #1939
  • Add a Template default value source for Hidden fields using sandboxed Craft object templates. Resolved server-side on render and submit; posted values are ignored. Custom Value behaviour is unchanged. (#2605)
  • Add rich text editing for field Instructions, including Craft entry links with target="_blank", configurable via rich-text.json under fields.instructions. Legacy plain-text and markdown instructions are normalized automatically without migration. (#724)
  • Add Craft-style attribute maps and merge helpers for setFieldSettings() field overrides, including mergeInputAttributes and mergeContainerAttributes. (#2510)
  • Add a Note builder field for form-builder guidance with Tip, Warning, Info, and Error styles. (#2498)
  • Add a Rich Text cosmetic field for WYSIWYG content in the form builder, configurable via rich-text.json under fields.content. (#1028, #1709, Discussion #2070, Discussion #772)
  • Add a syntax-highlighted HTML code editor for HTML cosmetic fields in the form builder, with project config via html.json. (#2181)
  • Add a Custom Field form-builder field backed by opt-in Craft field adapters. (#2208)
  • Add Google Maps field support to Custom Field fields. (#625)
  • Add Maps field support to Custom Field fields. (#626)
  • Add Craft Link field support to Custom Field fields, covering URL, email, phone and SMS link values. (#718)
  • Add dynamic Option Source settings for Dropdown, Radio and Checkboxes, allowing options to be populated from predefined option sets and other structured sources. (#2684)
  • Add a Use Searchable Dropdown setting for Dropdown fields, element relation fields when Display type is Dropdown, and Recipients when shown as a dropdown. The front end loads Formie’s combobox browser module so users can filter predefined options. (#960)
  • Add support for changing compatible field types in the form builder, initially limited to simple string-like fields such as Single-Line Text and Email Address. Existing submissions are not rewritten. (Discussion #2110)
  • Add Settings → Fields → Field Builder policy settings for Allow Multi-Select Dropdowns and Allow Phone Country Selector. When disabled, the corresponding field settings are hidden in the form builder and forced off on existing fields. (Discussion #2484, Discussion #2485)
  • Add Date Range collection to Date/Time fields when Display Type is Calendar (Advanced), using Flatpickr range mode to collect a start and end date/time. (#2011)
  • Add calendar date validation for Date/Time Text Inputs and Dropdowns, rejecting impossible dates (for example February 31), enforcing configured Min Date / Max Date settings on those display types, and surfacing validation errors on the offending sub-field. (#1458)
  • Add smart State / Province behaviour for Address fields, with Text or Dropdown when available input modes, country-dependent subdivision loading, dynamic labels (State, Province, Prefecture, and so on), optional hiding when unused, searchable dropdowns, and datalist suggestions for text fallback. (#1416)
  • Add table column reference support for Calculations fields with explicit row scope (first, last, index, all, count, custom row expressions). Table columns now appear in the Calculations variable picker, with row targeting configured in the variable settings popover. (#1284)
  • Add failed notification alert recipients by Craft user group and additional email addresses. (#2226)
  • Add per-rule validation message overrides via a Validation form builder tab and the validationMessages field setting, with legacy errorMessage values migrated to validationMessages.required. (#1269)
  • Track and display who created and last updated a form in the form builder Settings tab footer and as optional forms index columns. (Discussion #2342)
  • Add an Autocomplete setting to single-line and multi-line text fields in the form builder Settings tab, with a searchable list of HTML autocomplete tokens. (Discussion #2764)
  • Document using {env:FORMIE_*} environment variable tokens in notification recipient fields. (#2676)
  • Add a page setting to place the submit button at the end of the last field row. (#2542)
  • Add control panel submission field condition behaviour with plugin and per-form settings to follow, collapse, or ignore front-end field and page conditions when editing submissions. (#2435)
  • Add a default country setting for Google Places address auto-complete fields. (#2721)
  • Add a configurable maximum email attachment size, and validate notification attach assets in the form builder. (#2697)
  • Add group-scoped form and submission permissions using stable form group handles, with optional per-form dedicated permissions via a new Use Dedicated Permissions form setting. (#1426, #1356, #2489, Discussion #1696)
  • Add built-in submission guards (honeypot, minimum submit time, replay protection) via a RunSubmissionGuardsTask screen-stage workflow task and Settings → Spam Protection controls.
  • Add suspicious text detection, maximum links screening, global submission throttling, and per-IP submission throttling under Settings → Spam Protection. (#1332, #1154, #1099)
  • Add Theme setting for Friendly Captcha (light/dark/auto). (#2907)
  • Add extensible TipTap nodes, marks, toolbar controls, and constrained TextStyle definitions across Formie editing, previews, and PHP rendering, including opt-in font family, font size, text/background color, line height, and Small caps controls.
  • Add csrfInput render option to control Craft CSRF hidden input output (true default, false to omit, or an options array such as { async: true } for statically cached pages). (#2121)
  • Add Enable Multi-Page Forms plugin setting to disable multi-page forms in the form builder. When disabled, authors cannot add pages and existing multi-page forms cannot be saved until reduced to a single page. (#2483)
  • Add a Last Edited By column to submission sources, tracking the Craft user who last saved a submission in the control panel. (#1403)
  • Add allowedSubmitMethods plugin setting to restrict form submission methods to Ajax only, page reload only, or both (#1751).
  • Redesign page Client Events with a dedicated Tracking tab, support for multiple named events per page, variable picker values, and server-resolved clientEvents payloads in Ajax submit responses (#888).
  • Add submission PDF downloads from the control panel and via craft.formie.generateSubmissionPdf() / craft.formie.getSubmissionPdfDownloadUrl() (#1213, Discussion #1273).
  • Add custom variable sources via Variables::EVENT_REGISTER_VARIABLES, exposing registered tokens in the variable picker and resolving them server-side when references are parsed. (#898)
  • Add an includeFlatpickrCss plugin setting to disable Formie’s bundled Flatpickr stylesheet when your project already provides its own. (#2341)
  • Add conditional submission status rules in the form builder Settings → Submissions tab, evaluated on the front end during submission processing. (#508)
  • Add conditional redirect rules under Behaviour → After Submit, with an optional Enable Redirect Rules toggle that overrides the default submit action when conditions match. (#830)
  • Add a stock Form Preview slide-out in the form builder, rendering the current form with Formie’s default templates, CSS, and JavaScript. (#370)
  • Add submission UID to the control panel submission sidebar and as an optional submissions index column. (#2404)
  • Add an opt-in setting to disable the submit button until the current page passes validation. (#1514)
  • Add Ajax-safe tab link state theme keys tabLinkCurrent and tabLinkInactive, with aliases for pageTabLinkActive, pageTabLinkInactive, and pageInactive (#1279).

Changed

  • Require Craft CMS 5 and PHP 8.2+.
  • Rebuild the form builder around React, schema-driven settings, and shared Plugin Kit components.
  • Replace the legacy bundled front-end theme/runtime with package-based browser and framework runtimes for server-rendered and client-rendered forms.
  • Route controller, managed client, GraphQL, draft, payment, notification, and integration processing through the staged submission workflow.
  • Move integration settings to PHP-defined schemas and front-end integration, captcha, address, payment, and field behavior to client modules.
  • Replace the Dropdown, Radio and Checkboxes option-table Disabled column with a row-menu Visible / Hidden / Disabled availability control (#1816). Hidden removes an option from the front-end form while preserving stored submission values and labels; Disabled renders the option with HTML disabled so it stays visible but cannot be selected. Legacy disabled: true option rows are treated as hidden. Non-default states are indicated in the options table with row background tints.
  • Rework multi-site propagation and translation to use each form’s source site (where it was created) instead of Craft’s global primary site. “Same language” and “Same site group” propagation modes now filter from the source site. Forms store a persisted sourceSiteId. (#84)
  • Stop routing user-authored form content (labels, placeholders, messages, options) through the formie translation category. Form copy is output from the database after site overrides are merged; formie.php is for Formie-owned UI strings only (#2907).
  • Replace text-limit counter {startTag}{num}{endTag} translation strings with Craft plural syntax and wire translated counter copy on the front end. (#2526)
  • Stream CSV/text report exports row-by-row to disk for memory-safe large datasets (#2497).
  • Use stable field references and normalized field values across notifications, calculations, conditions, integrations, GraphQL, exports, and historical submission content.
  • Update phone number values sent to integrations to use E164 format instead of international formatting. (Discussion #2731)
  • Improve integration queue job descriptions and debug output with form context (formId, formHandle, formTitle). (#2172)
  • OAuth integration redirect URIs now default to a Craft action URL instead of a site URL. Add an optional OAuth Redirect URI Override plugin setting. (#1333)
  • Store incomplete submissions and pending uploads in database-backed, tokenized records with expiry, capability checks, garbage collection, and idempotent payment replay handling.
  • Replace self-referential synced fields with shared definitions and per-form placements, and update stencils to use snapshot semantics and stable field-reference remapping.
  • Improve Submission Limits form settings UX (Apply Limit To, consolidated messaging) and clarify the distinction from global Submission Throttling abuse controls. Add Submission Limits author documentation. Discussion #1939
  • Improve HTML and Rich Text cosmetic field builder previews and control panel submission views to show rendered output instead of raw source where appropriate. (#2182)
  • Move Agree field checked/unchecked display labels to the Settings tab and clarify that submissions store a boolean; use getFieldValueAsString() for Yes/No-style output. (#2288)
  • Replace custom static-cache refresh snippets with built-in token refresh behavior and tighten anonymous route, CORS, file-upload, callback, and webhook handling.
  • Freeform 4/5 plugin migrations now process submissions in batches (default 100) to avoid memory exhaustion on large forms. Use php craft formie/migrate/freeform4 (or freeform5) with --batch-size, --submission-offset, --submission-limit, --submissions-only, and --skip-submissions for large migrations. (#2513)
  • Improve default theme color contrast for WCAG 2.2 AA — darker error text, muted helper text, and border-only control styling with split border tokens (#2475).

Fixed

  • Fixed rate-limit bypass, CSRF, XSS, information disclosure, payment verification, XML injection, submission permission, and redirect URL vulnerabilities.
  • Fix file-upload security checks for MIME types, extensions, active content, and filename normalization.
  • Fix plugin uninstall via project-config/apply failing when Formie stencil project config is removed after the formie_stencils table has already been dropped. (#1710)
  • Fix plugin migrations failing on production when allowAdminChanges is disabled because migrations attempted to write plugin settings to project config. (#2615)
  • Fix captcha provider credentials saved in the control panel being wiped when project config syncs on deploy. Site-scoped captcha settings are now preserved across deployments. (#2407)
  • Fix Salesforce integrations failing after Craft 5 / Formie 3 upgrades when OAuth tokens were migrated without instance_url, by falling back to stored integration settings and backfilling token values. (#2492)
  • Fix Stripe payments failing with “Invalid email address” when Payment Receipt is enabled but the mapped receipt email resolves empty (for example legacy {field.email} tokens or User Email while logged out). (#2262)
  • Fix payment amount parsing for locale-formatted dynamic values (for example 1,234.56, 1.750,00, and £750.00) on both the server and in the browser payment modules. (#2334)
  • Fix payment follow-up states (such as 3D Secure authentication) showing as red validation errors. Action-required and pending payment responses now render as neutral form notices, and Ajax submit payloads include paymentStatus, paymentMessage, paymentAction, and paymentDecision metadata. (#2660)
  • Fix external redirect payments (for example Mollie) leaving users on the status polling page when payment fails. Failed payments now redirect back to the original form URL with a flash error message. (#2502)
  • Fix Stripe and other payment follow-up submits re-validating one-time captcha tokens (for example reCAPTCHA v2 checkbox and hCaptcha), which caused duplicate-token spam failures on the second Ajax POST. Incomplete continuation submits now skip captcha screening, matching replay-token behaviour. (#2465)
  • Fix Opayo, Stripe, Paddle, and GoCardless payment integrations not resolving Billing Details field mappings from the form builder static table, so Name and Address fields are included in payment payloads again. (#2617)
  • Fix OAuth integrations reporting a successful connection when their access token was not persisted. (#2961)
  • Fix Zoho picklist mappings sending option metadata IDs instead of their API values. (#2959)
  • Fix User element integration silently skipping group assignment when a configured group UID no longer resolves. (#2909)
  • Fix Group nested field values being ignored in submission title format tokens and Element/integration field mappings when the picker stored a child field reference. (#2922)
  • Fix queued integrations losing submit-time context (referrer, IP address, HubSpot/Pardot tracking cookies) by persisting request metadata on the submission at submit time and hydrating integration context from it in queue workers. (#1379)
  • Fix Salesforce integration refresh failing when an enabled object such as Opportunity or Case is unavailable in the connected org. (#1551)
  • Fix Marketo OAuth connect failing when an empty scope parameter is sent with the client-credentials grant, and normalize API domains that include a trailing /rest segment. (#2718)
  • Fix Mailchimp integrations not exposing or formatting Address merge fields, which prevented mapping Formie Address fields to Mailchimp audiences that require ADDRESS data. (#2387)
  • Improve Pardot integration errors when an account does not support API v4 (legacy Pardot Classic). (#2642)
  • Fix Upload Manager returning “Invalid file upload field” when a File Upload field is nested under a Group (and related nested content-key paths), and writing staged asset ids under the correct nested input names. (#2948)
  • Fix Recent Submissions widget breaking the control panel because WidgetsVendorAsset published from a src/ path that is not shipped in the package (#2939).
  • Fix required File Upload fields using Upload Manager never passing client-side validation after a successful upload. (#2924)
  • Fix phone country dropdown flags not appearing on Craft Cloud. Flag sprites are inlined in the front-end bundle instead of loading from relative CSS asset paths. (#2529)
  • Fix file upload assets being deleted when trashing a submission with File Uploads → Delete files enabled, so restored submissions keep their uploaded files. (#1258)
  • Skip notification email attachments when the asset file cannot be read, instead of failing the entire send. (#2626)
  • Fix file upload validation allowing extensions such as .jfif that Craft cannot save as assets. (#2716)
  • Fix File Upload fields failing on submit when no upload location is set, by requiring the setting in the form builder and falling back to the plugin default volume when configured. (#2597)
  • Fix Ajax and multi-page File Upload fields losing their uploaded-file summary after step navigation or when editing existing submissions. (#2742, #1856, #1910)
  • Fix File Upload fields inside Repeater or Group fields not initializing upload persistence for nested inputs. (#1448)
  • Fix ActiveCampaign Email marketing contact payloads sending blank unmapped properties (now array_filter’d like the CRM path). (#2934)
  • Fix status-change notifications never sending: the trigger compared Submission::getStatus() as a status model, but it returns the handle string. (#2931)
  • Fix control panel submission saves running visitor page-flow and new-submission semantics on editExisting requests, which blocked status-change notifications, flipped completed submissions to incomplete, and overwrote the selected status. (#2932)
  • Fix form import with Update existing form not removing notifications deleted before export. Empty notifications arrays in the import payload now replace the form’s notifications instead of being ignored. (#1941)
  • Fix notification email preview and send failing when both From Name and From Email are set. (#2698)
  • Fix Recipients fields preserving the selected option label when multiple recipient options send to the same email address, using encrypted row identity tokens while keeping recipient emails private in front-end markup. (#2382)
  • Fix option field values appearing empty in notification “All Form Fields” summaries when options were overridden via Twig setFieldSettings(), by applying persisted submission snapshots when loading forms for email/export and falling back to stored option values when labels cannot be resolved. (#2350)
  • Sanitize notification queue job debug data to valid UTF-8 before re-serializing failed jobs, preventing queue rows from becoming unreadable when submission content contains invalid byte sequences. (#2344)
  • Improve notification mailer failure logging when Craft returns no transport error message, including CLI/queue context to help diagnose cron-only send failures. (#2610)
  • Validate literal email addresses in notification recipient settings so invalid addresses are caught when saving notifications. (#2712)
  • Fix email notification preview failing when a recipient setting references a non-email field. (#2537)
  • Fix final submit validating only the current page when a later page is conditionally hidden — isLastPage() / isFirstPage() now accept the submission so they skip unreachable pages the same way as getNextPage(). (#2927)
  • Fix page (and other form-builder) conditions showing an empty Value dropdown for Submission Status by always supplying status select options. (#2925)
  • Fix CP submission edit (Follow field conditions) always hiding pages whose conditions use {submission:*} tokens — the client now evaluates those from a submission snapshot instead of treating them as missing fields. (#2925)
  • Fix headless/Ajax validation error messages using the wrong locale by applying the target site language at submission time (#1545).
  • Apply spam behaviour (success/message) without attempting to persist discarded spam submissions when Save spam submissions is disabled, avoiding failed saves under bot load. (#2818)
  • Fix page-reload single-line and multi-line text limit validation rerenders so field error styling, form-level error messages, and scroll/focus behaviour match ajax submissions. (#1997)
  • Fix Address and other fixed-parent sub-field settings being unavailable in the form builder by restoring on-demand field type config loading for nested sub-field types. (#1416)
  • Fix submission status filters in the control panel returning no results when submissions were saved without a persisted statusId, and resolve status queries by display name as well as handle. (#2687)
  • Fix form usage counts and the form builder Usage tab omitting entries on disabled Craft sites. (#2612)
  • Fix the form builder Usage tab not listing elements that reference a form on non-primary sites, including when Craft stores a relation without a specific sourceSiteId. (#2695)
  • Fix dropdown field options not saving in the form builder when no default option is selected. (#2795)
  • Fix replacing a deleted field with a new field using the same handle requiring a two-step save in the form builder. (#1854)
  • Fix missing page-list validation indicators in the form builder when a form has no pages. (#2786)
  • Keep field error live regions mounted without reserving empty layout space, honour the configured announcement priority, and associate definition-driven errors with their controls. (#2954)
  • Fix required Multi-line Text fields with Rich Text enabled being skipped by client-side validation — the backing <textarea> lives in a display: none wrapper, so visibility is now judged from the rich-text editor host instead. (#2947)
  • Fix field validation errors relying on aria-errormessage alone — also merge the error message id into aria-describedby (keeping any instruction ids) so assistive tech with weak aria-errormessage support still announces the error. (#2946)
  • Fix element-field variable tokens with a property selector resolving empty (e.g. {field:<ref>:title}). Unindexed selectors now resolve against related elements and join multi-value results. (#2930)
  • Fix rich text toolbars always showing only Bold/Italic — pass buttons / linkOptions to pk-tiptap-editor instead of the obsolete *Attr prop names so configured buttons reach the element. (#2929)
  • Fix submitting a filled Date/Time field throwing Undefined property: DateFieldValue::$date during validation when resolving nested date/time paths (including Date fields inside Group/Repeater). (#2923)
  • Fix date dropdown fields rejecting year-only values with “Year cannot be blank” when other date parts are disabled. Partial date parts are stored via DateFieldValue without requiring a full calendar date. (#2261)
  • Fix Google Maps API script conflicts when Address field autocomplete and the Google Maps Craft plugin are used on the same page. Formie reuses an existing window.google instance instead of injecting a second Maps script. (#2041)
  • Fix Phone field country selector labels not respecting the field’s Country Language setting. (#2042)
  • Fix required asterisk indicator not appearing on Agree fields when the field label is hidden and consent copy is shown on the checkbox label. (#2333)
  • Fix Summary field Ajax refreshes ignoring custom themeConfig classes by round-tripping render-time theme config through the summary HTML endpoint (#1721).
  • Skip client-side validation for fields disabled by conditional logic, and disable conditionally hidden submit buttons so Enter no longer triggers hidden submit/next actions. (#2727, #1136, Discussion #1628)
  • Bound spam keyword scanning and spam log payloads so very large field values cannot stall PHP workers during spam handling. (#2065)
  • Fix Signature fields intermittently showing a misleading “browser does not support” message on multi-page forms, conditional fields, and late layout by retrying canvas sizing, watching visibility changes, and showing accurate status copy when initialization fails. (#2708)
  • Fix Dropdown, Radio and Checkboxes Disabled option availability not outputting HTML disabled on the front-end form. (#1816)
  • Prompt for confirmation when closing a field settings overlay with Escape (or backdrop/header close) only when the field has unsaved changes. Untouched new fields close immediately. (#2219)
  • Fix checkbox fields saving their default option values when explicitly unchecked on submit. (#2457)
  • Fix the Dutch translation mapping Auto to Automatisch, which incorrectly changed checkbox labels and values meaning “car”. (#2636)
  • Generate translatable date picker placeholders from the configured date and time formats when no custom placeholder is set. (#2464)
  • Initialise captcha placeholders immediately when multipage forms change page via tabs or Ajax Next, so Friendly Captcha and other providers mount on the visible page before submit. (#1893)
  • Tear down Cloudflare Turnstile widgets with remove() during remounts and apply CSP nonces to dynamically loaded captcha scripts where available, reducing console noise on strict CSP hosts. (#2535)
  • Wait for reCAPTCHA Enterprise readiness before executing score/policy challenges on multipage navigation. (#2224)
  • Fix redirect Entry selections on the Behaviour tab (and stencils) never persisting because save read submitActionEntryId instead of the posted submitActionEntry list. (#2926)
  • Fix rich-text links to internal pages opening in a new tab including rel="noopener noreferrer nofollow". Internal links now omit the attribute; external links keep it. (#2604)
  • Fix submit button conditions not applying on the front end. (#2568)

Deprecated

  • Deprecate legacy form render IDs, asset helpers, render options, runtime-named classes and JavaScript translation hooks in favor of the new render IDs, formAssets() / frontendAssets() helpers, client/frontend naming, and package-based runtimes.
  • Deprecate legacy HTML tag APIs in favor of slot tag APIs.
  • Deprecate JSON, variable, email, and legacy key field-value APIs in favor of array, reference, and reference-block APIs.
  • Deprecate legacy custom field schema, preview, and input-template APIs in favor of defineFormBuilder*Schema(), defineFormBuilderPreviewSchema(), and getInputTemplatePath().
  • Deprecate legacy integration settings, front-end variables, payment processing, and submission dispatch helpers in favor of schema settings, client modules, and workflow services.
  • Deprecate legacy Formie DOM and validator events, GraphQL client-event setting names, refresh-token parameters, theme config keys, and schema config keys.
  • Deprecate the PredefinedOptions service and namespace in favor of OptionSources and the verbb\formie\options\predefined namespace.

Removed

  • Remove the legacy CustomElement submission model, FieldLegacy trait, Formie 3 field inputHtml() fallback, and expired field name helpers.
  • Remove the old JavaScript form bus, built-in front-end bundle assumptions, and getFrontEndJsVariables() integration API.
  • Remove the Duplicate, JavaScript, and Honeypot captcha integrations and the Algolia address provider.
  • Remove file, Redis, Memcached, and session-backed submission progression; Formie 4 uses database-backed state and no longer exposes submissionStateMode or submissionStore.
  • Remove enableGatsbyCompatibility and direct templateHtml usage from the primary GraphQL rendering path.
  • Require GraphQL submission mutations to pass the applicable submission guards and a bootstrap requestToken for headless transports.

Don't miss a new formie release

NewReleases is sending notifications on new releases.