Building a Reusable Filter Component in Laravel Livewire: A Step-by-Step Guide
Table of Contents
Livewire is an open-source library for Laravel, enhancing the development of dynamic and interactive user interfaces with minimal effort. Unlike traditional JavaScript-heavy solutions, Livewire allows developers to write interactive, reactive UI components using PHP, Blade, and Laravel's existing functionality. This library enables seamless server-client communication, allowing for real-time updates without requiring a page reload, providing a smooth and responsive user experience.
By leveraging Livewire, developers can create components such as forms, charts, and dynamic content areas, without the need to write complex JavaScript. The library simplifies the development process by allowing you to define your components in pure PHP, reducing the complexity of handling client-side behavior. Livewire works by automatically sending updates from the server to the client, ensuring that the interface stays in sync with the application's state. This makes it an ideal choice for building modern, real-time applications while maintaining Laravel's elegant syntax and structure.
Filtering is a crucial feature in many web applications, especially for managing data-heavy interfaces like admin dashboards or user portals. With Laravel Livewire, creating reusable components becomes seamless, allowing you to implement filters across multiple modules efficiently. In this guide, we will build a reusable common filter component using Laravel Livewire, enhancing code reusability and user experience.
Preview:
Step 1: Set Up Laravel with Livewire
Before diving into the implementation, ensure you have a Laravel project set up with Livewire installed. I took an Example for PG : Payment Gateway to filter transactions.
-
Open your terminal and run the following command to create a fresh Laravel
application:
composer create-project laravel/laravel PG
-
Next, install Livewire using this command:
composer require livewire/livewire
Step 2: Create the Livewire Trait
To avoid repetitive code, we will create a reusable Livewire trait that handles common filter logic.
- Generate a Livewire trait using:
php artisan livewire:make Admin\\Common\\FilterTrait
-
Open FilterTrait.php and add the following code:
namespace App\Livewire\Admin\Common; use Livewire\Component; class FilterTrait extends Component { public $filter_search_columns = [ "pg_transactions" => [ ["column" => "txn_ref_id","label"=>"PG Transaction ID"], ["column" => "order_id","label"=>"Order ID"], ["column" => "biller_id","label"=>"Biller ID"], ["column" => "payment_id","label"=>"Payment ID"] ], ]; public $filter_search_column = ""; public $filter_search_column_label = ""; public $filter_search = ""; public $filter_from_date = ""; public $filter_to_date = ""; public $filter_status = ""; public $filter_type = ""; public $filter_page_limit = 10; public $page_limits = [10,20,30,40,50,100]; public function set_filter_search_column($column_id=0,$page){ $column_id = base64_decode($column_id); $column = $this->filter_search_columns[$page][$column_id]; $this->filter_search_column = $column['column']; $this->filter_search_column_label = $column['label']; } public function filterRender(){ $this->resetPage(); } public function resetFilter($page=null) { if($page){ $this->set_filter_search_column(base64_encode(0),$page); } $this->filter_search = ""; $this->filter_from_date = ""; $this->filter_to_date = ""; $this->filter_status = ""; $this->filter_type = ""; $this->filter_page_limit = 10; $this->resetPage(); } // public function render() // { // return view('livewire.admin.common.filter-trait'); // } }
This trait will handle common filter functionalities like column selection, search, date filtering, and pagination.
Step 3: Create a Database and Model
- Generate a model and migration for transactions:
php artisan make:model PG\\PgTransactionModel -m
- Define Migration Schema Update the generated migration file with the following
structure:
Open database/migrations/xxxx_xx_xx_create_pg_transaction_models_table.php and add the following code:
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('pg_transactions', function (Blueprint $table) { $table->id(); $table->string('biller_id')->nullable(); $table->string('txn_ref_id')->nullable(); $table->timestamp('txn_date')->nullable(); // Stores "txnDate" $table->string('txn_status')->nullable(); // Stores "txnStatus" $table->string('product_name')->nullable(); $table->string('product_type')->nullable(); $table->string('currency')->nullable(); $table->decimal('amount', 15, 2)->default(0.00); $table->string('order_id')->index(); $table->string('store_id')->nullable(); $table->string('payment_mode')->nullable(); $table->string('payment_method')->nullable(); $table->string('payment_id')->nullable(); ; $table->string('ref_id_1')->nullable(); $table->string('ref_id_2')->nullable(); $table->string('ref_id_3')->nullable(); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('pg_transactions'); } };
-
Run the Migration Execute the migration to create the table: Ensure Your Database is
Properly Configured.
php artisan migrate
-
Update the Model Open app\Models\PG\PgTransactionModel.php and define
relationships and fillable fields
namespace App\Models\PG; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use App\Models\Biller; class PgTransactionModel extends Model { use HasFactory; protected $table = "pg_transactions"; protected $fillable = [ 'biller_id', 'txn_ref_id', 'txn_date', 'txn_status', 'product_name', 'product_type', 'currency', 'amount', 'order_id', 'store_id', 'payment_mode', 'payment_method', 'payment_id', 'ref_id_1', 'ref_id_2', 'ref_id_3', ]; public function biller() { return $this->hasOne(Biller::class, "biller_id", "biller_id"); }
Step 4: Build a Component with Filters
-
Generate a Livewire Component Create a new Livewire component for the transaction
list:
php artisan make:livewire Admin\\PG\\Transactions\\index
-
Inherit and Use FilterTrait Open app\Livewire\Admin\PG\Transactions\Index.php
and add the filter logic:
use App\Livewire\Admin\Common\FilterTrait; class Index extends FilterTrait { }
Full Code here.
namespace App\Livewire\Admin\PG\Transactions; use Livewire\Component; use Livewire\Attributes\{Computed,On,Locked,Title}; use Illuminate\Support\Facades\Auth; use Livewire\WithPagination; use Livewire\WithoutUrlPagination; use App\Livewire\Admin\Common\FilterTrait; use App\Models\PG\PgTransactionModel; class Index extends FilterTrait { use WithPagination, WithoutUrlPagination; public $page = 'pg_transactions'; public $page_id = ""; public function mount(){ $this->authorizeAdminUser(); $this->set_filter_search_column(base64_encode(0),$this->page); } public function render() { $component_records = $this->getTransactionData(); return view('livewire.admin.p-g.transactions.index',[ 'component_records' => $component_records ])->extends('admin.layouts.app')->title('Online Payment - PG Transactions'); } protected function authorizeAdminUser() { $user = Auth::guard('admin')->user(); if (!$user || !$user->hasAnyRole(['super-admin', 'admin', 'blog-manager'])) { abort(403); } } protected function getTransactionData(){ $new_query = PgTransactionModel::with("biller"); if(!empty($this->filter_search)){ $new_query = $new_query->where($this->filter_search_column,"LIKE","%".$this->filter_search."%"); } if($this->filter_status!==""){ $new_query = $new_query->where("txn_status",$this->filter_status); } if(!empty($this->filter_from_date) && !empty($this->filter_to_date)){ $new_query = $new_query->whereBetween('created_at', [$this->filter_from_date, $this->filter_to_date]); } $records = $new_query->latest()->paginate($this->filter_page_limit); return $records; } }
-
Design the View Open
resources\views\livewire\admin\p-g\transactions\index.blade.php file and add
this code
PG Transactions History
A pretty helpful component to show emphasized information to the user.
Transactions ListtoBiller Transaction ID Order ID Amount Date Status {{ $record->biller->biller_category }} {{ $record->biller->biller_name }} {{ $record->txn_ref_id }} {{ $record->order_id }} {{ $records_info['currency'] ?? 'INR' }} {{ $record->amount }} {{ $record->txn_date }} @if ($record->txn_status == 'SUCCESS') Success @elseif($record->txn_status == 'FAILED') Failed @else Pending @endif Record does not exist. @endforelse
Step 5: Set Up Routes
Add a route: Open routes/web.php and define the transaction route:
use App\Livewire\Admin\{PG};
//PG Transaction
Route::get('/pg/transactions', PG\Transactions\Index::class)->name('pg.transactions');
Step 6: Run the Project and Navigate to the Browser
- Serve the application locally:
php artisan serve
This will start the server and provide you with a local URL to access your application.
Access the Component in the Browser Open your preferred web browser and navigate to:
http://localhost:8000/admin/pg/transactions
Conclusion
In conclusion, creating a reusable filter component in Laravel Livewire is a powerful way to streamline your development process. By implementing the FilterTrait, you can centralize filter logic, enhance code reusability, and reduce redundancy across components. We hope this step-by-step guide has been insightful. Feel free to share your feedback or thoughts on this approach—your input is always appreciated!
0 Comments