Steps
A long form can be split into steps that are shown one at a time, with a step indicator ("Step 1 of 3"), large
Back and Next buttons and the submit button on the last step. Wrap the fields of each step in a Step:
use TranquilTools\FormBuilder\Fields\Step;
public function fields(): array
{
return [
Step::make('when')
->title('When and where')
->fields([
Select::make('room_id')->label('Room')->rules(['required']),
DateTime::make('starts_at')->label('Starts at')->touchPicker()->rules(['required']),
]),
Step::make('who')
->title('Renter')
->description('Pick an existing renter or add a new one.')
->fields([
Select::make('renter_id')->label('Renter')->searchable()->if("type === 'rental'"),
]),
Step::make('details')
->title('Details')
->fields([
Textarea::make('notes')->label('Notes'),
]),
Submit::make()->label('Save'),
];
}
- A
Stepis aSection: it takestitle(),description()andcolumns(), and its fields' rules are part of the form'srules()as usual. The name (when) identifies the step for the slots below; without one the steps are calledstep-1,step-2and so on. - Fields outside the steps are shown on the last step, below its own fields. A
Submitfield outside the steps is not rendered as such: its label becomes the label of the submit button on the last step. - A step whose fields are all hidden by their
->if()condition is skipped, and the step indicator counts it out. AStepcan have an->if()of its own as well. - Pressing Enter in a field moves to the next step instead of submitting the form.
- When the submit fails with validation errors, the form jumps back to the first step that has one, and that step is marked red in the indicator.
- The step indicator gives every visible step the same width. A long title wraps to two lines and is then cut off. On a phone (below 640 px) it shows only the numbered circles, and the current step's title is the heading below.
- Earlier steps can be reopened with Back or by tapping their number. Later steps are only reached with Next.
Keeping the step across a reload
Pass remember to <Form> to keep the typed values and the current step when the page is reloaded halfway, see
Vue Usage:
<Form :schema="form" remember />
Validating each step on the server
By default Next moves on without a check, and the server validates everything on submit. With
validateSteps(), Next first asks the server to validate the fields of the current step, with a
Laravel Precognition request, and only moves on when they pass:
public function configure(FormConfig $form): void
{
$form->validateSteps();
}
The route the form submits to must use the HandlePrecognitiveRequests middleware, otherwise the request runs
the controller and saves the form:
use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests;
Route::resource('bookings', BookingController::class)
->middlewareFor(['store', 'update'], HandlePrecognitiveRequests::class);
- The controller action must validate with a form request (a
FormRequestparameter, for example one whoserules()returnsYourForm::rules()). Precognition runs the form request and stops before the action itself, so validating inside the action withYourForm::make()->validate($request)checks nothing and every step passes. - The request goes to the form's action with the form's method (spoofed with
_method), the whole form as JSON andPrecognition-Validate-Onlyset to the visible fields of the step. Your form request validates only those, so a rule likeafter:starts_atstill sees the other values. Authorisation runs as usual. - A
204with thePrecognition: trueheader counts as valid. A422shows the errors at the fields and keeps the step. Anything else (a500, a dropped connection, a204without the header) keeps the step and shows "Checking this step failed, try again". - File fields are left out of the step check and are validated on submit.
- A form with method
GETnever checks its steps.
Slots
Each step has two slots on <Form>, step-{name}-before and step-{name}-after, rendered above and below the step's
fields. They receive form and step:
<Form :schema="form">
<template #step-who-after="{ form }">
<button type="button" @click="openRenterDialog">+ New renter</button>
</template>
<template #step-details-before="{ form }">
<BookingSummary :values="form" />
</template>
</Form>
The step texts ("Step 1 of 3", "Back", "Next", "Save", "Checking...") are in the form messages under stepOf,
previousStep, nextStep, save and checkingStep, see Vue Usage.
Requires tranquil-tools/laravel-form-builder 1.10 and laravel-vue-form-builder 1.14 or newer.
