Laravel 10 Livewire Wizard Multi Step Tutorial

Step 1 : Install Laravel


composer create-project laravel/laravel livewire-app

Step 2 : Create Migration and Model


    php artisan make:migration create_products_table

Migration:


    <?php
   
    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;
       
    return new class extends Migration
    {
        /**
         * Run the migrations.
         */
        public function up(): void
        {
            Schema::create('products', function (Blueprint $table) {
                $table->id();
                $table->string('name')->nullable();
                $table->longText('description')->nullable();
                $table->float('amount')->nullable();
                $table->boolean('status')->default(0);
                $table->integer('stock')->default(0);
                $table->timestamps();
            });
        }
      
        /**
         * Reverse the migrations.
         */
        public function down(): void
        {
            Schema::dropIfExists('products');
        }
    };

    php artisan migrate

Now, we will create Product model

App/Models/Product.php


    php artisan make:model Product

    <?php
  
    namespace App\Models;
      
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Database\Eloquent\Model;
      
    class Product extends Model
    {
        use HasFactory;
     
        /**
         * The attributes that are mass assignable.
         *
         * @var array
         */
        protected $fillable = [
            'name', 'amount', 'description', 'status', 'stock'
        ];
    }

Step 3: Install Livewire


    composer require livewire/livewire

Step 4: Create Component

so run bellow command to create add more component. 


    php artisan make:livewire wizard

Now they fies path below:


    app/Http/Livewire/Wizard.php
    resources/views/livewire/wizard.blade.php

Now both file we will update as bellow for our contact us form.

app/Http/Livewire/Wizard.php


    <?php
  
    namespace App\Http\Livewire;
      
    use Livewire\Component;
    use App\Models\Product;
      
    class Wizard extends Component
    {
        public $currentStep = 1;
        public $name, $amount, $description, $status = 1, $stock;
        public $successMessage = '';
      
        /**
         * Write code on Method
         *
         * @return response()
         */
        public function render()
        {
            return view('livewire.wizard');
        }
      
        /**
         * Write code on Method
         *
         * @return response()
         */
        public function firstStepSubmit()
        {
            $validatedData = $this->validate([
                'name' => 'required|unique:products',
                'amount' => 'required|numeric',
                'description' => 'required',
            ]);
     
            $this->currentStep = 2;
        }
      
        /**
         * Write code on Method
         *
         * @return response()
         */
        public function secondStepSubmit()
        {
            $validatedData = $this->validate([
                'stock' => 'required',
                'status' => 'required',
            ]);
      
            $this->currentStep = 3;
        }
      
        /**
         * Write code on Method
         *
         * @return response()
         */
        public function submitForm()
        {
            Product::create([
                'name' => $this->name,
                'amount' => $this->amount,
                'description' => $this->description,
                'stock' => $this->stock,
                'status' => $this->status,
            ]);
      
            $this->successMessage = 'Product Created Successfully.';
      
            $this->clearForm();
      
            $this->currentStep = 1;
        }
      
        /**
         * Write code on Method
         *
         * @return response()
         */
        public function back($step)
        {
            $this->currentStep = $step;    
        }
      
        /**
         * Write code on Method
         *
         * @return response()
         */
        public function clearForm()
        {
            $this->name = '';
            $this->amount = '';
            $this->description = '';
            $this->stock = '';
            $this->status = 1;
        }
    }

resources/views/livewire/wizard.blade.php


    <div>
   
    @if(!empty($successMessage))
    <div class="alert alert-success">
       {{ $successMessage }}
    </div>
    @endif
      
    <div class="stepwizard">
        <div class="stepwizard-row setup-panel">
            <div class="stepwizard-step">
                <a href="#step-1" type="button" class="btn btn-circle {{ $currentStep != 1 ? 'btn-default' : 'btn-primary' }}">1</a>
                <p>Step 1</p>
            </div>
            <div class="stepwizard-step">
                <a href="#step-2" type="button" class="btn btn-circle {{ $currentStep != 2 ? 'btn-default' : 'btn-primary' }}">2</a>
                <p>Step 2</p>
            </div>
            <div class="stepwizard-step">
                <a href="#step-3" type="button" class="btn btn-circle {{ $currentStep != 3 ? 'btn-default' : 'btn-primary' }}" disabled="disabled">3</a>
                <p>Step 3</p>
            </div>
        </div>
    </div>
      
        <div class="row setup-content {{ $currentStep != 1 ? 'displayNone' : '' }}" id="step-1">
            <div class="col-xs-12">
                <div class="col-md-12">
                    <h3> Step 1</h3>
      
                    <div class="form-group">
                        <label for="title">Product Name:</label>
                        <input type="text" wire:model="name" class="form-control" id="taskTitle">
                        @error('name') <span class="error">{{ $message }}</span> @enderror
                    </div>
                    <div class="form-group">
                        <label for="description">Product Amount:</label>
                        <input type="text" wire:model="amount" class="form-control" id="productAmount"/>
                        @error('amount') <span class="error">{{ $message }}</span> @enderror
                    </div>
      
                    <div class="form-group">
                        <label for="description">Product Description:</label>
                        <textarea type="text" wire:model="description" class="form-control" id="taskDescription">{{{ $description ?? '' }}}</textarea>
                        @error('description') <span class="error">{{ $message }}</span> @enderror
                    </div>
      
                    <button class="btn btn-primary nextBtn btn-lg pull-right" wire:click="firstStepSubmit" type="button" >Next</button>
                </div>
            </div>
        </div>
        <div class="row setup-content {{ $currentStep != 2 ? 'displayNone' : '' }}" id="step-2">
            <div class="col-xs-12">
                <div class="col-md-12">
                    <h3> Step 2</h3>
      
                    <div class="form-group">
                        <label for="description">Product Status</label><br/>
                        <label class="radio-inline"><input type="radio" wire:model="status" value="1" {{{ $status == '1' ? "checked" : "" }}}> Active</label>
                        <label class="radio-inline"><input type="radio" wire:model="status" value="0" {{{ $status == '0' ? "checked" : "" }}}> DeActive</label>
                        @error('status') <span class="error">{{ $message }}</span> @enderror
                    </div>
      
                    <div class="form-group">
                        <label for="description">Product Stock</label>
                        <input type="text" wire:model="stock" class="form-control" id="productAmount"/>
                        @error('stock') <span class="error">{{ $message }}</span> @enderror
                    </div>
      
                    <button class="btn btn-primary nextBtn btn-lg pull-right" type="button" wire:click="secondStepSubmit">Next</button>
                    <button class="btn btn-danger nextBtn btn-lg pull-right" type="button" wire:click="back(1)">Back</button>
                </div>
            </div>
        </div>
        <div class="row setup-content {{ $currentStep != 3 ? 'displayNone' : '' }}" id="step-3">
            <div class="col-xs-12">
                <div class="col-md-12">
                    <h3> Step 3</h3>
      
                    <table class="table">
                        <tr>
                            <td>Product Name:</td>
                            <td><strong>{{$name}}</strong></td>
                        </tr>
                        <tr>
                            <td>Product Amount:</td>
                            <td><strong>{{$amount}}</strong></td>
                        </tr>
                        <tr>
                            <td>Product status:</td>
                            <td><strong>{{$status ? 'Active' : 'DeActive'}}</strong></td>
                        </tr>
                        <tr>
                            <td>Product Description:</td>
                            <td><strong>{{$description}}</strong></td>
                        </tr>
                        <tr>
                            <td>Product Stock:</td>
                            <td><strong>{{$stock}}</strong></td>
                        </tr>
                    </table>
      
                    <button class="btn btn-success btn-lg pull-right" wire:click="submitForm" type="button">Finish!</button>
                    <button class="btn btn-danger nextBtn btn-lg pull-right" type="button" wire:click="back(2)">Back</button>
                </div>
            </div>
        </div>
    </div>

Step 5: Create Route

now we will create one route for calling our example, so let's add new route to web.php file as bellow:

routes/web.php


    Route::get('wizard', function () {
        return view('default');
    });

Step 6: Create View File

resources/views/default.blade.php 


    <!DOCTYPE html>
    <html>
    <head>
        <title>Laravel Livewire Example - webthestuff.com</title>
        @livewireStyles
        <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
        <link href="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
        <script src="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
      
        <link href="{{ asset('wizard.css') }}" rel="stylesheet" id="bootstrap-css">
    </head>
    <body>
        
    <div class="container">
        
        <div class="card">
          <div class="card-header">
            Laravel Livewire Wizard Form Example - webthestuff.com
          </div>
          <div class="card-body">
            <livewire:wizard />
          </div>
        </div>
            
    </div>
        
    </body>
     
    @livewireScripts
      
    </html>

public/wizard.css


    body{ 
        margin-top:40px; 
    }
    .stepwizard-step p {
        margin-top: 10px;
    }
    .stepwizard-row {
        display: table-row;
    }
    .stepwizard {
        display: table;
        width: 100%;
        position: relative;
    }
    .stepwizard-step button[disabled] {
        opacity: 1 !important;
        filter: alpha(opacity=100) !important;
    }
    .stepwizard-row:before {
        top: 14px;
        bottom: 0;
        position: absolute;
        content: " ";
        width: 100%;
        height: 1px;
        background-color: #ccc;
        z-order: 0;
    }
    .stepwizard-step {
        display: table-cell;
        text-align: center;
        position: relative;
    }
    .btn-circle {
      width: 30px;
      height: 30px;
      text-align: center;
      padding: 6px 0;
      font-size: 12px;
      line-height: 1.428571429;
      border-radius: 15px;
    }
    .displayNone{
      display: none;
    }

Run Laravel App:


    php artisan serve

Now, Go toweb browser, type the given URL and view the output:


    http://localhost:8000/wizard