Skip to content

[6.x] Forms 2: Multi-page forms & SubmitForm action#14840

Draft
duncanmcclean wants to merge 38 commits into
forms-2from
forms-2-submit-form-action
Draft

[6.x] Forms 2: Multi-page forms & SubmitForm action#14840
duncanmcclean wants to merge 38 commits into
forms-2from
forms-2-submit-form-action

Conversation

@duncanmcclean

@duncanmcclean duncanmcclean commented Jun 18, 2026

Copy link
Copy Markdown
Member

This pull request adds support for handling multi-page form submissions and implements a re-usable SubmitForm action.

Multipage forms

Note

While this PR adds support for handling multi-page form submissions in Statamic Core, you'll need to install the Forms Pro addon (paid) to use them.

This PR adds support for handling multi-page form submissions with the {{ form:create }} tag without needing to update your templates.

The {{ sections }} and {{ fields }} loops are automatically scoped to the current page. The page's display name, help text (instructions) and button labels are available in the form tag:

{{ form:multi_page_form }}
    <h2>{{ page:display }}</h2>
    <p>{{ page:instructions }}</p>

    {{ if success }}
        Success!
    {{ /if }}

    {{ sections }}
        <fieldset>
            <legend>{{ display }}</legend>
            {{ form:fields }}
                <div>
                    <label>{{ display }}</label>
                    <p>{{ instructions }}</p>
                    {{ field }}
                    {{ if error }}
                        <p>{{ error }}</p>
                    {{ /if }}
                </div>
            {{ /form:fields }}
        </fieldset>
    {{ /sections }}

    {{ if previous_page_url }}
        <a href="{{ previous_page_url }}">{{ previous_page_label }}</a>
    {{ /if }}

    <button>{{ button_label }}</button>
{{ /form:multi_page_form }}

Upon submitting a page, Statamic will validate its fields and create a "partial" form submission (see #14832). This partial submission will be "finalized" when the final page is submitted, triggering emails, etc.

Multi-page forms can be used in conjunction with Statamic's Alpine & Alpine Precognition JS drivers.

Forms Pro will ship with its own Alpine drivers allowing you to maintain page state on the frontend and submit page values over AJAX for a more seamless experience.

Static Caching

Fields are now pre-populated using values from the user's partial submission, to ensure values are kept when navigating between pages.

For this reason, we recommend wrapping all forms in the {{ nocache }} tag.

SubmitForm addon

This PR also extracts the form submission logic from Statamic's FormController into a reusable SubmitForm action class, making it easier for third-party developers to submit forms via Livewire components or custom API endpoints.

use Statamic\Facades\Form;
use Statamic\Facades\Site;
use Statamic\Forms\SubmitForm;
use Statamic\Exceptions\SilentFormFailureException;
use Illuminate\Validation\ValidationException;

$form = Form::find('contact');

try {
    $submission = app(SubmitForm::class)
        ->form($form)
        ->submit(
            data: ['name' => 'John', 'email' => 'john@example.com'],
            files: [], // Optional
        );
} catch (ValidationException $e) {
    return back()->withErrors($e->errors());
} catch (SilentFormFailureException $e) {
    // Honeypot triggered or event listener rejected
    // $e->submission() contains the submission data

    return back()->with('success', 'Form submitted successfully!');
}

return back()->with('success', 'Form submitted successfully!');

Methods

Method Description
form Provide the Form you want to use.
page ID of the page you want to submit.
resume Submission instance of the partial submission you wish to resume.
submit Submit the form. Accepts an array of $data and an optional array of $files. Returns a SubmissionResult object containing the submission and the ID of the next page (in the case of a multi-page form).
validate Validate the current page. Accepts an array of $data and an optional array of $files. Also accepts an array of field handles to limit which fields are validated.

Precognition

Validation used to live in a FrontendFormRequest, which is where Precognition was handled.

However, now that validation lives in the action, the form request has been deleted and Precognition is now handled explicitly in the controller. It validates via the action (scoped to the Precognition-Validate-Only fields) and halts without storing a submission.

Laravel's HandlePrecognitiveRequests middleware short-circuts the controller before its code is executed, so the form route uses a slim HandleFormPrecognitiveRequests subclass which keeps Precognition detection and headers but lets the request reach the controller.


Replaces #14375
Replaces #14867
Depends on #14832
Closes statamic/ideas#1409

@duncanmcclean duncanmcclean changed the title [6.x] Forms 2: SubmitForm action [6.x] Forms 2: SubmitForm action & Multi-page forms Jun 26, 2026
@duncanmcclean duncanmcclean changed the title [6.x] Forms 2: SubmitForm action & Multi-page forms [6.x] Forms 2: Multipage forms & SubmitForm action Jun 26, 2026
@duncanmcclean duncanmcclean changed the title [6.x] Forms 2: Multipage forms & SubmitForm action [6.x] Forms 2: Multi-page forms & SubmitForm action Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant