satoved/laravel-livewire-steps
Lightweight Laravel Livewire 3 wizard/multi-step form builder. Define each step as a Livewire Form object (extends StepForm) and manage the flow in a single WizardComponent. Ideal for onboarding, checkout, and subscription flows with minimal setup.
Installation:
composer require satoved/laravel-livewire-steps
Publish the config (if needed):
php artisan vendor:publish --provider="Satoved\LivewireSteps\LivewireStepsServiceProvider"
First Use Case: Create a Livewire component for your wizard:
php artisan make:livewire WizardComponent
Define steps as form objects in the component:
use Satoved\LivewireSteps\LivewireSteps;
use Livewire\Attributes\Rule;
public function mount()
{
$this->steps = [
new StepOneForm(),
new StepTwoForm(),
// Add more steps as needed
];
}
public function render()
{
return LivewireSteps::make($this->steps);
}
Register the Component: Add the component to your Blade view:
@livewire('wizard-component')
Form Objects as Steps:
Each step is a Livewire form object (class extending Livewire\Component).
Example:
class StepOneForm extends Livewire\Component
{
public $name;
public function rules()
{
return ['name' => 'required|min:3'];
}
public function render()
{
return view('steps.step-one');
}
}
Step Navigation:
Use nextStep() and prevStep() methods provided by the package:
public function nextStep()
{
$this->validate();
$this->steps->next();
}
public function prevStep()
{
$this->steps->prev();
}
Multi-Step Forms:
LivewireSteps::make() to render the wizard UI.Dynamic Steps: Load steps dynamically based on user input:
public function mount()
{
$this->steps = collect();
if ($this->shouldShowStepOne()) {
$this->steps->push(new StepOneForm());
}
if ($this->shouldShowStepTwo()) {
$this->steps->push(new StepTwoForm());
}
}
Custom UI: Override the default template by publishing views:
php artisan vendor:publish --tag=livewire-steps-views
Then customize resources/views/vendor/livewire-steps/steps.blade.php.
Validation: Validate each step before proceeding:
protected $rules = [
'step_one.name' => 'required',
'step_two.email' => 'required|email',
];
Progress Tracking:
Use the currentStep property to track progress:
public function render()
{
return view('livewire.wizard', [
'currentStep' => $this->steps->current(),
'totalSteps' => $this->steps->count(),
]);
}
Final Submission: Handle form submission after all steps are completed:
public function submit()
{
$this->validate();
// Save data or perform final action
session()->flash('success', 'Form submitted successfully!');
}
Step Indexing:
Ensure steps are indexed correctly in the steps array/collection. Out-of-order steps may cause navigation issues.
Form State Persistence: Livewire form objects retain state between steps. Clear data if needed:
public function resetForm()
{
$this->reset();
$this->steps->each(fn ($step) => $step->reset());
}
Validation Errors: Validate each step before proceeding to avoid silent failures. Use:
public function nextStep()
{
$this->validate();
$this->steps->next();
}
Step Navigation Issues:
Check if nextStep()/prevStep() methods are correctly bound to buttons in the Blade view.
Form Data Loss:
Ensure all form objects are properly instantiated and retained in the steps property.
UI Rendering: If the wizard doesn’t render, verify:
LivewireSteps::make() method is called in the render() method.Livewire\Component.Default Configuration:
The package uses minimal configuration. Customize via config/livewire-steps.php if needed:
'default_step' => 0, // Start from step 0
'allow_back' => true, // Allow going back to previous steps
Step Classes:
Ensure step classes are autoloaded. If using namespaces, register them in composer.json:
"autoload": {
"psr-4": {
"App\\Steps\\": "app/Steps/"
}
}
Custom Templates: Override the default Blade templates for steps, progress bars, or navigation buttons.
Step Events: Listen for step changes via Livewire hooks:
protected $listeners = ['stepChanged' => 'handleStepChange'];
public function handleStepChange($step)
{
// Custom logic when step changes
}
Dynamic Step Loading: Load steps asynchronously if they are resource-intensive:
public function loadStep($stepClass)
{
$this->steps->push(new $stepClass());
}
How can I help you explore Laravel packages today?