Laravel 11 Livewire Wizard Multi Step Form Tutorial
In this tutorial, I would like to share with you how to create wizard multi step form using livewire in laravel 11 application.
Livewire is a full-stack framework for Laravel that makes building dynamic interfaces simple, without leaving the comfort of Laravel. If you are using Livewire with Laravel, then you don't need to worry about writing jQuery AJAX code; Livewire will help you write jQuery AJAX code using PHP in a very simple way. Without page refresh, Laravel validation will work, the form will be submitted, etc.
Here, I will give you a very simple example of a multi-step form using Bootstrap wizard design. We will create a products table with name, description, amount, status, and stock columns. Then, in the first step, the user will be able to enter name, description, and amount details and click on the next step. In the second step, the user will be able to select status and add stock. Then, in the last step, the user will see all the information and submit it.
So, let's follow the bellow step and you will get the layout:
Step for Laravel 11 Livewire Wizard Multi Step Form Example
- Step 1: Install Laravel 11
- Step 2: Create Migration and Model
- Step 3: Install Livewire
- Step 4: Create Component
- Step 5: Create Route
- Step 6: Create View File
- Run Laravel App:
Step 1: Install Laravel 11
First of all, we need to get a fresh Laravel 11 version application using the command below because we are starting from scratch. So, open your terminal or command prompt and run the command below:
composer create-project laravel/laravel example-app
Step 2: Create Migration and Model
Here, we need to create a database migration for the files table, and also, we will create a model for the files table.
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');
}
};
Then run migration command.
php artisan migrate
Now we will create the Product model using the following command:
php artisan make:model Product
App/Models/Product.php
<?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
Now in this step, we will simply install Livewire to our Laravel application using the below command:
composer require livewire/livewire
Step 4: Create Component
Now here we will create a Livewire component using their command. So run the following command to create an add more component.
php artisan make:livewire wizard
Now they created files on both paths:
app/Livewire/Wizard.php
resources/views/livewire/wizard.blade.php
Now, both files we will update as below for our contact us form.
app/Livewire/Wizard.php
<?php
namespace App\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 mt-3 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 mt-3 pull-right" type="button" wire:click="secondStepSubmit">Next</button>
<button class="btn btn-danger nextBtn mt-3 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 mt-3 pull-right" wire:click="submitForm" type="button">Finish!</button>
<button class="btn btn-danger nextBtn mt-3 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 a new route to the web.php file as below:
routes/web.php
<?php
use Illuminate\Support\Facades\Route;
Route::get('wizard', function () {
return view('default');
});
Step 6: Create View File
Here, we will create a Blade file for the call form route. In this file, we will use @livewireStyles, @livewireScripts, and @livewire('wizard'). So let's add it.
resources/views/default.blade.php
<!DOCTYPE html>
<html>
<head>
<title>Laravel Livewire Wizard Form Example - ItSolutionStuff.com</title>
@livewireStyles
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
<link href="{{ asset('wizard.css') }}" rel="stylesheet" id="bootstrap-css">
</head>
<body>
<div class="container">
<div class="card mt-5">
<h3 class="card-header p-3">Laravel 11 Livewire Wizard Form Example - ItSolutionStuff.com</h3>
<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:
All the required steps have been done, now you have to type the given below command and hit enter to run the Laravel app:
php artisan serve
Now, Go to your web browser, type the given URL and view the app output:
http://localhost:8000/wizard
Output:
I hope it can help you...
Hardik Savani
I'm a full-stack developer, entrepreneur and owner of ItSolutionstuff.com. I live in India and I love to write tutorials and tips that can help to other artisan. I am a big fan of PHP, Laravel, Angular, Vue, Node, Javascript, JQuery, Codeigniter and Bootstrap from the early stage. I believe in Hardworking and Consistency.
We are Recommending you
- Laravel 11 Livewire Form Validation Example
- How to Create Custom Validation Rules in Laravel 11?
- Laravel 11 CKeditor Image Upload Example
- Laravel 11 Restrict User Access from IP Address Example
- How to Create ZIP Archive File in Laravel 11?
- Laravel 11 Livewire CRUD using Jetstream & Tailwind CSS
- Laravel 11 Google Autocomplete Address Example
- Laravel 11 Ajax Dependent Dropdown Example
- How to Save JSON Data in Database in Laravel 11?
- Setup Automatic Daily Database Backup with Laravel 11
- Laravel 11 CRUD with Image Upload Tutorial
- Laravel 11 Razorpay Payment Gateway Integration Example
- How to Install and Configuration Telescope in Laravel 11?
- Laravel 11 Google Recaptcha V3 Validation Tutorial
- Laravel 11 Image Intervention Tutorial With Example