How to Add Date range filter with Livewire pagination in Laravel

Using pagination you can divide a large list of records into multiple pages and show a limited number of records per page.

But if the search filter is not available with pagination then traversing the paginated result becomes difficult.

In this tutorial, I show how you can add a date range filter with Livewire pagination in Laravel 9.

In the example, I am using jQuery UI library for datepicker.

How to Add Date range filter with Livewire pagination 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->date('dateofjoining');
       $table->smallInteger('status');
       $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, dateofjoining, 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','dateofjoining','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 – Using this property change the default pagination theme from Tailwind to bootstrap. If you are using Tailwind in your project then remove this property.
    • $from_date – Store selected from date from datepicker.
    • $to_date – Store selected to date from datepicker.
    • $orderColumn – Assign sorting column name. Change its value while implementing in your project.
    • $sortOrder – Assign sorting order – asc or desc. I set it asc.
  • Class methods –
    • updated() – Using this reset the pagination layout during date filtering.
    • render() – Fetch records from employees table. Use class variables for setting orderby(). If from_date and to_date are not empty then search on dateofjoining field using between. Paginate the fetched records by calling paginate(10).

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 $from_date = "";
      public $to_date = "";

      public $orderColumn = "emp_name";
      public $sortOrder = "asc";

      public function updated(){
           $this->resetPage();
      }

      public function render(){ 

           $employees = Employees::orderby($this->orderColumn,$this->sortOrder)->select('*');
           if(!empty($this->from_date) && !empty($this->to_date)){
                $employees->whereBetween('dateofjoining', [$this->from_date, $this->to_date]);
           }
           $employees = $employees->paginate(10);

           return view('livewire.emp-pagination', [
               'employees' => $employees,
           ]);

      }
}

resources/views/livewire/emp-pagination.blade.php

  • Create 2 textbox element for datepicker –
    • 1st is for from date. Add wire:model="from_date".
    • 2nd is for to date. Add wire:model="to_date".
  • Create <table > to list $employees record if it is not empty. If it is empty then show No record found row.
  • Display pagination links using {{ $employees->links() }}.

Script –

  • Initialize datepicker on #from_date and #to_date.
  • Using onSelect event to update from_date and to_date model value after date selection.
  • To update need to call @this.set(). Here, pass the model variable name and value.

Completed Code

<div>

    <div class="container">
         <div class="row mt-5">

             <div class="col-md-12">

                  <!-- Date range filter -->
                  <div class="search-filter">
                       <input type="text" class="datepicker" id="from_date" wire:model="from_date">
                       <input type="text" class="datepicker" id="to_date" wire:model="to_date"> 
                  </div>

                  <!-- Paginated records -->
                  <table class="table">
                      <thead>
                           <tr>
                               <th >Name</th>
                               <th >Email</th>
                               <th >Gender</th>
                               <th >City</th>
                               <th >Date of Joining</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->dateofjoining }}</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>

@section('scripts')
<script>
$(document).ready(function(){

    $("#from_date").datepicker({
        dateFormat: "yy-mm-dd",
        changeYear: true,
        changeMonth: true,
        onSelect: function (selected) {
             var dt = new Date(selected);

             @this.set('from_date', selected);

             dt.setDate(dt.getDate() + 1);
             $("#to_date").datepicker("option", "minDate", dt);
        }
    });

    $("#to_date").datepicker({
        dateFormat: "yy-mm-dd",
        changeYear: true,
        changeMonth: true,
        onSelect: function (selected) {
             var dt = new Date(selected);

             @this.set('to_date', selected);

             dt.setDate(dt.getDate() - 1);
             $("#from_date").datepicker("option", "maxDate", dt);
        }
    });
});
</script>
@endsection

7. Create View

Create index.blade.php file in resources/views/ folder.

Include jQuery and jQuery UI library –

<!-- jQuery UI CSS -->
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/themes/smoothness/jquery-ui.css">

<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>

<!-- jQuery UI JS -->
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>

Include emp-pagination component, livewire style, and script. Also, add @yield('scripts').

Completed Code

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>How to Add Date range filter with Livewire pagination in Laravel</title>

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" >

    <!-- jQuery UI CSS -->
    <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/themes/smoothness/jquery-ui.css">

    <!-- jQuery -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>

    <!-- jQuery UI JS -->
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>

    @livewireStyles

    <style type="text/css">
    .datepicker{
        width: 200px;
        display: inline-block;
    }
    </style>
</head>
<body>

    <livewire:emp-pagination />

    @livewireScripts

    @yield('scripts')

</body>
</html>

8. Output

View Output


9. Conclusion

In the example, I used jQuery UI library for datepicker but you can use any other library that you are compatible with.

Make sure to call @this.set() after date selection to update the model value otherwise, data will not filter.

You can view this tutorial if you want to know how you add textbox search filter with Livewire pagination.

If you found this tutorial helpful then don't forget to share.

Leave a Comment