Pagination is very useful when you have to show a huge list of records on the page. It divides the records into multiple pages.
Limited number of records shown at a time.
Livewire has provided the WithPagination trait for generating pagination. Its implementation is similar to Laravel default pagination.
In this tutorial, I show how you can create Livewire pagination with search filter and sorting in Laravel 9.

Contents
- Add Database configuration
- Create a Table
- Create Model
- Create Controller
- Create Route
- Create Livewire Component
- Create View
- Output
- Conclusion
1. Add Database configuration
Open .env file to update the database connection.
Specify the host, database name, username, and password.
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=tutorial DB_USERNAME=root DB_PASSWORD=
2. Create a Table
- Create a table
employeesusing migration.
php artisan make:migration create_employees_table
- Now, navigate to
database/migrations/folder from the project root. - Find a PHP file that ends with
create_employees_tableand open it. - Define the table structure in the
up()method.
public function up()
{
Schema::create('employees', function (Blueprint $table) {
$table->id();
$table->string('emp_name',60);
$table->string('email',80);
$table->string('gender',20);
$table->string('city',100);
$table->smallInteger('status',2);
$table->timestamps();
});
}
- Run the migration –
php artisan migrate
- The table is been created and I added some records to it.
3. Create Model
- Create
EmployeesModel –
php artisan make:model Employees
- Open
app/Models/Employees.phpfile. - Specify mass assignable Model attributes – emp_name, email, gender, city, and status using the
$fillableproperty.
Completed Code
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Employees extends Model
{
use HasFactory;
protected $fillable = [
'emp_name','email','gender','city','status'
];
}
4. Create Controller
- Create
EmployeesControllercontroller.
php artisan make:controller EmployeesController
- Open
app\Http\Controllers\EmployeesController.phpfile. - Create 1 method –
- index() – Load
indexview.
- index() – Load
Completed Code
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class EmployeesController extends Controller
{
public function index(){
return view('index');
}
}
5. Create Route
- Open
routes/web.phpfile. - Define 1 route –
- / – Load index view.
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\EmployeesController;
Route::get('/', [EmployeesController::class, 'index']);
6. Create Livewire Component
Create emp-pagination component –
php artisan make:livewire emp-pagination
This will create 2 files –
- app/Http/Livewire/EmpPagination.php
- resources/views/livewire/emp-pagination.blade.php
app/Http/Livewire/EmpPagination.php
- Include
Livewire\WithPaginationtrait andApp\Models\Employeesmodel. - Create 5 property variables –
- $paginationTheme – Livewire pagination by default uses Tailwind CSS. If you are using Bootstrap in your project then you can change it to bootstrap using
$paginationThemeproperty. - $orderColumn – Store sorting order column name. I set it to
emp_name. - $sortOrder – Store sorting order – asc or desc.
- $sortLink – Use to store sorting icon.
- $searchTerm – Use for data binding.
- $paginationTheme – Livewire pagination by default uses Tailwind CSS. If you are using Bootstrap in your project then you can change it to bootstrap using
- Class methods –
- updated() – Using this reset the pagination layout while searching.
- sortOrder() – Using this method update values of order by.
This method takes column name as parameter. If sortOrder == 'asc' then assign desc to $this->sortOrder and down to $caretOrder otherwise, assign asc to $this->sortOrder and up to $caretOrder.
Update $sortLink icon and assign $columnName to $this->orderColumn.
-
- render() – Fetch records from the
employeestable. Here, use$this->orderColumnand$this->sortOrderfor sorting records.
- render() – Fetch records from the
If $searchTerm is not empty then search on emp_name and city fields using like. Generate pagination by calling paginate(10). You can change the number from 10 to 5,15,25, etc according to your requirement.
Load livewire.emp-pagination view and pass $employees.
Completed Code
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use Livewire\WithPagination;
use App\Models\Employees;
class EmpPagination extends Component
{
use WithPagination;
protected $paginationTheme = 'bootstrap';
public $orderColumn = "emp_name";
public $sortOrder = "asc";
public $sortLink = '<i class="sorticon fa-solid fa-caret-up"></i>';
public $searchTerm = "";
public function updated(){
$this->resetPage();
}
public function sortOrder($columnName=""){
$caretOrder = "up";
if($this->sortOrder == 'asc'){
$this->sortOrder = 'desc';
$caretOrder = "down";
}else{
$this->sortOrder = 'asc';
$caretOrder = "up";
}
$this->sortLink = '<i class="sorticon fa-solid fa-caret-'.$caretOrder.'"></i>';
$this->orderColumn = $columnName;
}
public function render(){
$employees = Employees::orderby($this->orderColumn,$this->sortOrder)->select('*');
if(!empty($this->searchTerm)){
$employees->orWhere('emp_name','like',"%".$this->searchTerm."%");
$employees->orWhere('city','like',"%".$this->searchTerm."%");
}
$employees = $employees->paginate(10);
return view('livewire.emp-pagination', [
'employees' => $employees,
]);
}
}
resources/views/livewire/emp-pagination.blade.php
- Create a text element for searching. Add
wire:model="searchTerm"to it. - Create
<table >and if$employeeshave records then loop on$employeesto create new<tr>. If not then showNo record foundmessage. - For sorting add
wire:clickon header column that callssortOrder(). Here, pass the column name. - Add
{!! $sortLink !!}to display sort order icon. - Show pagination links using –
$employees->links().
Completed Code
<div>
<div class="container">
<div class="row mt-5">
<div class="col-md-12">
<!-- Search box -->
<input type="text" class="form-control" placeholder="Search Name or city" style="width: 250px;" wire:model="searchTerm" >
<!-- Paginated records -->
<table class="table">
<thead>
<tr>
<th class="sort" wire:click="sortOrder('emp_name')">Name {!! $sortLink !!}</th>
<th class="sort" wire:click="sortOrder('email')">Email {!! $sortLink !!}</th>
<th class="sort" wire:click="sortOrder('gender')">Gender {!! $sortLink !!}</th>
<th class="sort" wire:click="sortOrder('city')">City {!! $sortLink !!}</th>
<th>Status</th>
</tr>
</thead>
<tbody>
@if ($employees->count())
@foreach ($employees as $employee)
<tr>
<td>{{ $employee->emp_name }}</td>
<td>{{ $employee->email }}</td>
<td>{{ $employee->gender }}</td>
<td>{{ $employee->city }}</td>
<td>{{ $employee->status }}</td>
</tr>
@endforeach
@else
<tr>
<td colspan="5">No record found</td>
</tr>
@endif
</tbody>
</table>
<!-- Pagination navigation links -->
{{ $employees->links() }}
</div>
</div>
</div>
</div>
7. Create View
Create index.blade.php file in resources/views/ folder.
Include emp-pagination component and also include livewire style and script.
Completed Code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Create Livewire pagination with search filter and sorting in Laravel</title>
<!-- Fontawesome -->
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css">
<!-- Bootstrap -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" >
@livewireStyles
<style type="text/css">
.sorticon{
visibility: hidden;
color: darkgray;
}
.sort:hover .sorticon{
visibility: visible;
}
.sort:hover{
cursor: pointer;
}
</style>
</head>
<body>
<livewire:emp-pagination />
@livewireScripts
</body>
</html>
8. Output
9. Conclusion
In the example, I have added a search box with pagination similarly you can add other elements for filtering.
You can also view this tutorial to know livewire pagination with date range filter.
If you found this tutorial helpful then don't forget to share.