Laravel Livewire | How to Build a CRUD Application with Pagination (Tall Stack Example)

Raviya Technical
4 min readApr 19, 2023

Step 1: Install Laravel

composer create-project laravel/laravel laravel

Step 2: Create Dummy Records using Tinker Factory

php artisan tinker
User::factory()->count(100)->create()

Step 3: Install Tall Stack

Step 4: Create Component

php artisan make:livewire Users/UserList

Now they created fies on both path:

app/Http/Livewire/Users/UserList.php 

resources/views/livewire/users/user-list.blade.php

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

app/Http/Livewire/Users/UserList.php

<?php

namespace App\Http\Livewire\Users;

use Livewire\Component;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Livewire\WithPagination;

class UserList extends Component
{
use WithPagination;

public $name, $email, $password;
public $user_id;

/**
* The attributes that are mass assignable.
*
* @var array
*/
public function render()
{
return view('livewire.users.user-list',[
'users' => User::paginate(15)
]);
}

/**
* The attributes that are mass assignable.
*
* @var array
*/
private function resetInputFields()
{
$this->name = '';
$this->email = '';
$this->password = '';
}

/**
* The attributes that are mass assignable.
*
* @var array
*/
public function edit($id)
{
$user = User::findOrFail($id);
$this->user_id = $id;
if ($user) {
$this->name = $user->name;
$this->email = $user->email;
}
}

/**
* The attributes that are mass assignable.
*
* @var array
*/
public function cancel()
{
$this->user_id = null;
$this->resetInputFields();
}

/**
* The attributes that are mass assignable.
*
* @var array
*/
public function save()
{
$validatedData = $this->validate([
'name' => 'required',
'email' => 'required|email',
'password' => ($this->user_id) ? 'nullable' : 'required',
'user_id' => 'nullable'
]);

if (!empty($validatedData['password'])) {
$validatedData['password'] = Hash::make($validatedData['password']);
} else {
unset($validatedData['password']);
}
$userQuery = User::query();
if (!empty($validatedData['user_id'])) {
$user = $userQuery->find($validatedData['user_id']);
if ($user) {
$user->update($validatedData);
}
} else {
$userQuery->create($validatedData);
}

$this->user_id = null;
session()->flash('message', 'User Created Successfully.');
$this->resetInputFields();
}

/**
* The attributes that are mass assignable.
*
* @var array
*/
public function delete($id)
{
$user = User::find($id);
if ($user) {
$user->delete();
}
session()->flash('message', 'User Deleted Successfully.');
}
}

Make Componet

php artisan make component Forms/Input --view

resources/views/components/forms/input.blade.php

@props(['type' => 'text', 'label', 'name', 'value', 'placeholder', 'required'])

<div class="mb-6">
<label for="{{ $name }}"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">{{ $label }}</label>
<input type="{{ $type }}" wire:model.defer="{{ $name }}" id="{{ $name }}"
name="{{ $name }}" value="{{ $value }}"
class="block w-full p-2 text-gray-900 border border-gray-300 rounded-lg bg-gray-50 sm:text-xs focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="{{ $placeholder }}" @if ($required) required @endif>
@error($name)
<span class="mt-2 text-sm text-red-600 dark:text-red-500">{{ $message }}</span>
@enderror
</div>

resources/views/livewire/users/user-list.blade.php

<div>
@if (session()->has('message'))
<div class="alert alert-success">
{{ session('message') }}
</div>
@endif

<form
class="w-full max-w-sm p-4 mt-4 mb-4 bg-white border border-gray-200 rounded-lg shadow sm:p-6 dark:bg-gray-800 dark:border-gray-700">
<input type="hidden" wire:model="user_id">
<x-forms.input type="text" label="Name" name="name" value="{{ old('name') }}" placeholder="Enter Name"
required />
<x-forms.input type="email" label="Email" name="email" value="{{ old('email') }}" placeholder="Enter Email"
required />
<x-forms.input type="password" label="Password" name="password" value="{{ old('password') }}"
placeholder="Enter Password" required />
<button wire:click.prevent="save()"
class="px-3 py-2 text-sm font-medium text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Save</button>
<button wire:click.prevent="cancel()"
class="px-3 py-2 text-sm font-medium text-center text-white bg-red-700 rounded-lg hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-800">Cancel</button>
</form>
<div class="relative overflow-x-auto shadow-md sm:rounded-lg">
<table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<tr>
<th scope="col" class="px-6 py-3">
No.
</th>
<th scope="col" class="px-6 py-3">
Name
</th>
<th scope="col" class="px-6 py-3">
Email
</th>
<th scope="col" class="px-6 py-3">
Action
</th>
</tr>
</thead>
<tbody>
@php
$i = (request()->input('page', 1) - 1) * 15;
@endphp
@foreach ($users as $key => $user)
<tr class="bg-white border-b dark:bg-gray-900 dark:border-gray-700">
<th scope="row"
class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
{{-- {{ $user->id }} --}}
{{ ++$i }}
</th>
<td class="px-6 py-4">
{{ $user->name }}
</td>
<td class="px-6 py-4">
{{ $user->email }}
</td>
<td class="px-6 py-4">
<button wire:click="edit({{ $user->id }})"
class="font-medium text-blue-600 dark:text-blue-500 hover:underline">Edit</button>
<button wire:click="delete({{ $user->id }})"
class="font-medium text-blue-600 dark:text-blue-500 hover:underline">Delete</button>
</td>
</tr>
@endforeach
</tbody>
</table>
<div class="p-3">
{{ $users->links() }}
</div>
</div>
</div>

Step 5: Create Route

Create controller UserController

php artisan make:controller UserController

app/Http/Controllers/UserController.php

<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class UserController extends Controller
{
public function index()
{
return view('users.index');
}
}

routes/web.php

 Route::get('users', [UserController::class, 'index'])->name('users.index');

Step 6: Create View File

resources/views/users/index.blade.php

@extends('layouts.app')
@section('content')
@livewire('users.user-list')
@endsection

Run Laravel App:

Now you can run using bellow command:

php artisan serve

Open bellow URL:

http://localhost:8000/users

I hope it can help you...

--

--