Filament Tip – Wizards and Validation

Filament has a feature known as Wizards, which allows for multi-step forms.

See Filament Form Wizards

One of the challenges, as indicated on this tutorial – Form Wizard with Auto-Save Draft is that you can only have required fields on the first step. This is because the validation fires and reviews all validation requirements across the form, not just within the step you’re working on.

It might not be the only way possible, nor the best way, but the way it was possible to work around this limitation was to leverage the isConcealed property and is set for hidden and disabled fields.

Note: This in theory only works cleanly if skippableSteps is false.

Within the Filament Form schema definition, set a Hidden field to track the active step

Hidden::make("wizard_step")->dehydrated(false),

For each step, before Validation starts (beforeValidation), we grab the the current ‘step’

->beforeValidation(function (string $context, Set $set) {
/** @var Wizard $wizard */
$wizard = $this->form->getComponent(fn (Component $component): bool => $component instanceof Wizard);
$set("wizard_step", $wizard->getCurrentStepIndex());
})

In subsequent steps, use a ‘Section’ to group all elements together, and hide them where the current step is before that step.

})->hidden(
function (Get $get): bool {
return $get("wizard_step") < 1;
}),

To ensure the step is re-exposed as it is entered, in an ‘afterValidation’ closure, we increase the step count right at the end (which presumes validation was not halted

/** @var Wizard $wizard */
$wizard = $this->form->getComponent(fn (Component $component): bool => $component instanceof Wizard);
$set("wizard_step", $wizard->getCurrentStepIndex()+1);

That’s it! It was then possible to use rules/required flags on every other step.