Create Livewire pagination with Search filter and Sorting in Laravel

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.

Create Livewire pagination with search filter and sorting in Laravel


Contents

  1. Add Database configuration
  2. Create a Table
  3. Create Model
  4. Create Controller
  5. Create Route
  6. Create Livewire Component
  7. Create View
  8. Output
  9. 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 employees using 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_table and 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 Employees Model –
php artisan make:model Employees
  • Open app/Models/Employees.php file.
  • Specify mass assignable Model attributes – emp_name, email, gender, city, and status using the $fillable property.

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 EmployeesController controller.
php artisan make:controller EmployeesController
  • Open app\Http\Controllers\EmployeesController.php file.
  • Create 1 method –
    • index() – Load index view.

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.php file.
  • 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\WithPagination trait and App\Models\Employees model.
  • 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 $paginationTheme property.
    • $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.
  • 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 employees table. Here, use $this->orderColumn and $this->sortOrder for sorting records.

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 $employees have records then loop on $employees to create new <tr>. If not then show No record found message.
  • For sorting add wire:click on header column that calls sortOrder(). 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

View 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.

Leave a Comment