Work with Laravel 8 Livewire Wizard Form Guide

Reading Time: 11 minutes
6,774 Views

In many web applications we can see the multi step form wizard. We will have step by step form inputs which takes value and then finally submit data.

Inside this article we are going to see the concept of Laravel 8 Livewire Wizard Form. This is new feature added in laravel 8 version. Livewire came with amazing Form Wizard feature. This will be quite interesting blog article.

Let’s get started about step by step Livewire Form wizard setup.


Laravel Installation

We will create laravel project using composer. So, please make sure your system should have composer installed. If not, may be this article will help you to Install composer in system.

Here is the command to create a laravel project-

composer create-project --prefer-dist laravel/laravel blog

To start the development server of Laravel –

php artisan serve

URL: http://127.0.0.1:8000

Assuming laravel already installed inside your system.

Also Database configured with application.


Install Livewire

We need to install livewire into laravel 8 setup. Open application into terminal and run this command.

$ composer require livewire/livewire

Create Livewire Wizard Component

We are going to create a Livewire wizard component. So we have to run the given command into terminal.

$ php artisan make:livewire wizard

After running this command, it will create few files. One is to handle wizard functionality and other is responsible to render form inputs step by step.

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

Create Model & Migration File

We are going to create a form wizard to create a student. In that step up form we have some input fields and accordingly we will have form submission.

So, let’s create a model and migration for student module. Back to terminal and run this command.

$ php artisan make:model Student -m

By the help of this command we are going to create Model and a migration file. -m is for migration file. We have now two more files at

  • /app/Models/Student.php
  • /database/migrations/2020_11_16_161423_create_students_table.php

Open Student.php model file.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Student extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
        'registration_id',
        'gender',
        'mobile',
        'address'
    ];
}

Open migration file

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateStudentsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('students', function (Blueprint $table) {
            $table->id();
            $table->string("name", 50);
            $table->string("registration_id", 15);
            $table->enum("gender", ["male", "female", "others"]);
            $table->string("mobile", 15);
            $table->text("address");
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('students');
    }
}

Back to terminal and run this migrate command to run all pending migrations of application.

$ php artisan migrate

Updating Livewire Component Files

Open file /app/Http/Livewire/Wizard.php , copy and paste the given code.

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\Student;

class Wizard extends Component
{
    public $currentStep = 1;
    public $name, $registration_id, $gender, $address, $mobile;
    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',
            'registration_id' => 'required',
            'gender' => 'required',
        ]);
 
        $this->currentStep = 2;
    }
  
    /**
     * Write code on Method
     *
     * @return response()
     */
    public function secondStepSubmit()
    {
        $validatedData = $this->validate([
            'address' => 'required',
            'mobile' => 'required',
        ]);
  
        $this->currentStep = 3;
    }
  
    /**
     * Write code on Method
     *
     * @return response()
     */
    public function submitForm()
    {
        Student::create([
            'name' => $this->name,
            'registration_id' => $this->registration_id,
            'gender' => $this->gender,
            'address' => $this->address,
            'mobile' => $this->mobile,
        ]);
  
        $this->successMessage = 'Student 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->registration_id = '';
        $this->gender = '';
        $this->mobile = '';
        $this->address = '';
    }
}

We have provided the core functionality with Laravel validation inside this Wizard class. This class is going to do everything like

  • Step up wizard form validation
  • Render Form layouts
  • Save data to database

Open up the file /resources/views/livewire/wizard.blade.php to create form layout

<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="name">Name:</label>
                    <input type="text" wire:model="name" class="form-control">
                    @error('name') <span class="error">{{ $message }}</span> @enderror
                </div>
                <div class="form-group">
                    <label for="registration_id">Registration ID:</label>
                    <input type="text" wire:model="registration_id" class="form-control"/>
                    @error('registration_id') <span class="error">{{ $message }}</span> @enderror
                </div>

                <div class="form-group">
                    <label for="gender">Select Gender:</label>
                    <select wire:model="gender" class="form-control">
                        <option>Choose Option</option>
                        <option value="male">Male</option>
                        <option value="female">Female</option>
                        <option value="others">Others</option>
                    </select>
                    @error('gender') <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="mobile">Mobile</label><br />
                    <input type="text" wire:model="mobile" class="form-control"/>
                    @error('mobile') <span class="error">{{ $message }}</span> @enderror
                </div>

                <div class="form-group">
                    <label for="address">Address</label>
                    <textarea wire:model="address" class="form-control"></textarea>
                    @error('address') <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>Name:</td>
                        <td><strong>{{$name}}</strong></td>
                    </tr>
                    <tr>
                        <td>Registration Id:</td>
                        <td><strong>{{ $registration_id }}</strong></td>
                    </tr>
                    <tr>
                        <td>Gender:</td>
                        <td><strong>{{ $gender }}</strong></td>
                    </tr>
                    <tr>
                        <td>Mobile:</td>
                        <td><strong>{{ $mobile }}</strong></td>
                    </tr>
                    <tr>
                        <td>Address:</td>
                        <td><strong>{{ $address }}</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>

Create Route

Next, we need to create laravel 8 route for wizard module. go to /routes/web.php

Add this given route into web.php file

//... other routes

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

Create View File

We have to create a layout file named as default.blade.php which will be at /resources/views and this file contains @livewireStyles, @livewireScripts, <livewire:wizard />

<!DOCTYPE html>
<html>

<head>
    <title>Laravel 8 Livewire Wizard Form Example - Online Web Tutor</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" style="text-align: center;">
                <h4>Laravel Livewire Wizard Form Example - Online Web Tutor</h4>
                <h5>Create a Student</h5>
            </div>
            <div class="card-body">
                <livewire:wizard />
            </div>
        </div>

    </div>

</body>

@livewireScripts

</html>

Create CSS file

At the above layout, we have included a CSS file. So we need to create that. Back to application /public and create wizard.css file into it. Open up the file and write the following code.

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;
}
.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;
}

.setup-content .error{
    color: red;
}

Application Testing

Run this command into project terminal to start development server,

php artisan serve

Open up the URL – 127.0.01:8000/wizard

We hope this article helped you to learn about Laravel 8 Livewire Wizard Form Guide Tutorial in a very detailed way.

Online Web Tutor invites you to try Skillshike! Learn CakePHP, Laravel, CodeIgniter, Node Js, MySQL, Authentication, RESTful Web Services, etc into a depth level. Master the Coding Skills to Become an Expert in PHP Web Development. So, Search your favourite course and enroll now.

If you liked this article, then please subscribe to our YouTube Channel for PHP & it’s framework, WordPress, Node Js video tutorials. You can also find us on Twitter and Facebook.

Sanjay KumarHello friends, I am Sanjay Kumar a Web Developer by profession. Additionally I'm also a Blogger, Youtuber by Passion. I founded Online Web Tutor and Skillshike platforms. By using these platforms I am sharing the valuable knowledge of Programming, Tips and Tricks, Programming Standards and more what I have with you all. Read more