Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Livewire Wizard Laravel Package

spatie/laravel-livewire-wizard

Lightweight Livewire components for building multi-step wizards in Laravel. Define a wizard with an ordered list of step components, each with its own screen and Livewire logic, and guide users through checkout-style flows with ease.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require spatie/laravel-livewire-wizard
    

    Publish the config (if needed):

    php artisan vendor:publish --provider="Spatie\LivewireWizard\LivewireWizardServiceProvider"
    
  2. First Use Case: Create a wizard component:

    php artisan make:livewire MultiStepWizard
    

    Define steps in MultiStepWizard.php:

    use Spatie\LivewireWizard\Traits\HasSteps;
    
    class MultiStepWizard extends Component
    {
        use HasSteps;
    
        public function mount()
        {
            $this->steps = [
                'step1' => 'First Step',
                'step2' => 'Second Step',
                'step3' => 'Final Step',
            ];
        }
    }
    
  3. Blade Integration:

    <livewire:multi-step-wizard />
    

Where to Look First

  • Documentation: Spatie's Livewire Wizard Docs (if available).
  • Example Components: Check the tests/ folder in the package for real-world usage patterns.
  • Config File: config/livewire-wizard.php for global settings (e.g., default step transitions).

Implementation Patterns

Core Workflow

  1. Define Steps: Use the HasSteps trait to declare steps programmatically or via config:

    $this->steps = [
        'step1' => [
            'name' => 'Personal Info',
            'component' => 'personal-info-step',
        ],
        'step2' => [
            'name' => 'Address',
            'component' => 'address-step',
            'canGoBack' => false, // Optional
        ],
    ];
    
  2. Step Components: Create Livewire components for each step (e.g., PersonalInfoStep.php):

    class PersonalInfoStep extends Component
    {
        public $name;
        public $email;
    
        public function submit()
        {
            $this->dispatch('step-submitted', data: ['name' => $this->name]);
        }
    }
    
  3. Navigation Logic: Use the wizard's built-in methods:

    public function nextStep()
    {
        $this->goToNextStep();
    }
    
    public function previousStep()
    {
        $this->goToPreviousStep();
    }
    
  4. Dynamic Steps: Load steps dynamically (e.g., from a database):

    public function mount()
    {
        $this->steps = Step::query()->pluck('name', 'slug')->toArray();
    }
    

Integration Tips

  • Validation: Validate step data before transitioning:

    public function nextStep()
    {
        $this->validate(['email' => 'required|email']);
        $this->goToNextStep();
    }
    
  • Progress Tracking: Use the currentStep property to show progress bars or indicators:

    <div class="progress">
        @foreach ($steps as $step => $name)
            <div class="step {{ $step === $currentStep ? 'active' : '' }}">
                {{ $name }}
            </div>
        @endforeach
    </div>
    
  • State Management: Pass data between steps via wire:model or events:

    // In Step 1
    $this->dispatch('update-step-data', data: ['email' => $this->email]);
    
    // In Step 2 (listen in Blade)
    <script>
        window.addEventListener('update-step-data', event => {
            @this.set('email', event.detail.data.email);
        });
    </script>
    
  • Conditional Steps: Hide/show steps based on logic:

    public function getStepsProperty()
    {
        $steps = [...];
        if ($this->isAdmin) {
            $steps['admin-step'] = 'Admin Settings';
        }
        return $steps;
    }
    

Gotchas and Tips

Pitfalls

  1. Step Component Registration:

    • Ensure step components are registered in the wizard's steps array. Forgetting this will cause blank screens or errors.
    • Fix: Verify components exist in resources/views/livewire/ or are properly namespaced.
  2. State Persistence:

    • Livewire wizards do not persist state across page reloads by default. Use sessions or a database for critical data.
    • Fix: Store step data in $this->persistentData or use Laravel's session:
      session()->put('wizard_data', $this->stepData);
      
  3. Event Conflicts:

    • Custom events (e.g., step-submitted) may conflict with other Livewire components.
    • Fix: Use unique event names or namespaces:
      $this->dispatch('wizard.step-submitted', data: [...]);
      
  4. Validation Timing:

    • Validation runs client-side only. Server-side validation is still required for security.
    • Fix: Re-validate on submission in the parent wizard:
      public function nextStep()
      {
          $this->validate();
          $this->goToNextStep();
      }
      

Debugging

  1. Step Not Rendering:

    • Check the currentStep property in the browser's dev tools. If it’s null, the wizard isn’t initialized.
    • Debug: Add {{ dd($currentStep) }} to the wizard blade template.
  2. Stuck Steps:

    • If a step fails to load, inspect the network tab for 404 errors (missing component views).
    • Debug: Temporarily simplify the steps array to isolate the issue.
  3. Transition Issues:

    • Use wire:ignore on dynamic content that might interfere with transitions:
      <div wire:ignore>
          {{ $dynamicContent }}
      </div>
      

Extension Points

  1. Custom Transitions: Override goToNextStep() or goToPreviousStep() to add logic:

    public function goToNextStep()
    {
        if (!$this->canProceed()) {
            session()->flash('error', 'Cannot proceed.');
            return;
        }
        parent::goToNextStep();
    }
    
  2. Step Metadata: Extend step definitions with custom attributes:

    $this->steps = [
        'step1' => [
            'name' => 'Intro',
            'component' => 'intro-step',
            'icon' => 'heroicon-o-information-circle',
            'requiresLogin' => true,
        ],
    ];
    
  3. Global Wizard Config: Customize default behavior in config/livewire-wizard.php:

    'default_step' => 'step1',
    'allow_skip' => true,
    'persist_data' => false,
    
  4. Testing: Use the LivewireWizardTestCase (if provided) or mock the trait:

    $wizard = new class extends LivewireComponent {
        use HasSteps;
        public $steps = ['test' => 'Test Step'];
    };
    $wizard->goToNextStep();
    $this->assertEquals('test', $wizard->currentStep);
    

Pro Tips

  • Reusable Wizards: Create a base wizard class to avoid repetition:

    class BaseWizard extends Component
    {
        use HasSteps;
    
        public function render()
        {
            return view('wizards.base', ['steps' => $this->steps]);
        }
    }
    
  • Localization: Localize step names dynamically:

    'name' => __("wizard.steps.{$step}"),
    
  • Performance: Lazy-load step components if they’re resource-intensive:

    public function mount()
    {
        $this->steps = collect(config('wizard.steps'))
             ->mapWithKeys(fn ($step) => [$step['slug'] => $step])
             ->toArray();
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport