Livewire Datatable with Filter and Sort Options

Bootstrap 5 Livewire

Demo

Datatables with Search and Filters

You can filter the data by searching for name/price/description, also use sorting and pagination.
Title Description Price
Amazon Basics In-Ear 10.99
Apple Airpods 79.99
Apple Airpods Pro 249
Beats Earbuds 35.63
Beats Solo3 170.49
Bose SoundSport 99
Cowin E7 59.99
Cowin E7 59.99
Cowin E7 59.99
Noot Kids K11 14.99

This is a pro component. Get Livewiredemos pro access to view / download the component code.

Component Class


<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\DummyProduct;
use Livewire\WithPagination;

class DataTableComponent extends Component
{
    use WithPagination;

    protected $paginationTheme = 'bootstrap';

    public $orderByColumn = 'title', $order = 'asc';
    protected $paginate = 10;

    public $searchColumns = [
        'title' => '',
        'description' => '',
        'price' => [
            'startingPrice' => '',
            'endingPrice' => '',
        ],
    ];

    public function render()
    {
        return view('livewire.data-table-component');
    }

    public function sortBy($column)
    {
        if ($this->orderByColumn == $column) {
            $this->order = $this->order == 'asc' ? 'desc' : 'asc';
        }

        $this->orderByColumn = $column;
    }

    public function getDummyProductsQueryProperty()
    {
        return DummyProduct::query()
            ->orderBy($this->orderByColumn, $this->order)
            ->when($this->searchColumns['title'], function ($query) {
                $query->whereLike('title', trim($this->searchColumns['title']));
            })
            ->when($this->searchColumns['description'], function ($query) {
                $query->whereLike('description', trim($this->searchColumns['description']));
            })
            ->when($this->searchColumns['price']['startingPrice'], function ($query) {
                $query->filterPrice('>=', trim($this->searchColumns['price']['startingPrice']));
            })
            ->when($this->searchColumns['price']['endingPrice'], function ($query) {
                $query->filterPrice('<=', trim($this->searchColumns['price']['endingPrice']));
            });
    }

    public function getDummyProductsProperty()
    {
        return $this->dummyProductsQuery->paginate($this->paginate);
    }
}

Component View File


<div class="tw-py-10">
    <div class="tw-mx-auto tw-max-w-7xl">
        <div class="tw-px-4 sm:tw-px-6 lg:tw-px-8">
            <div class="sm:tw-flex sm:items-center tw-mb-4">
                <h2 class="fw-bold blue-heading">
                    Datatables with Search and Filters
                </h2>
            </div>
            <div class="alert alert-info tw-m-0">
                You can filter the data by searching for name/price/description, also use
                sorting and pagination.
            </div>
            <div class="tw-mt-8 tw-flex tw-flex-col">
                <div class="tw--my-2 tw--mx-4 overflow-x-auto sm:tw--mx-6 lg:tw--mx-8">
                    <div class="tw-inline-block tw-min-w-full tw-py-2 tw-align-middle md:tw-px-6 lg:tw-px-8">
                        <div
                            class="tw-overflow-hidden tw-shadow tw-ring-1 tw-ring-black tw-ring-opacity-5 md:tw-rounded-lg">
                            <table class="tw-min-w-full tw-divide-y tw-divide-gray-300">
                                <thead class="tw-bg-gray-50">
                                    <tr>
                                        <th wire:click="sortBy('title')" scope="tw-col"
                                            class="tw-py-3.5 tw-pl-4 tw-pr-3 tw-text-left tw-text-sm tw-font-semibold tw-text-gray-900 sm:tw-pl-6 tw-cursor-pointer">
                                            Title
                                            @if ($this->order == 'asc' && $this->orderByColumn == 'title')
                                                <i class="fa fa-fw fa-sort-desc"></i>
                                            @elseif ($this->order == 'desc' && $this->orderByColumn == 'title')
                                                <i class="fa fa-fw fa-sort-asc"></i>
                                            @else
                                                <i class="fa fa-fw fa-sort"></i>
                                            @endif
                                            </span>
                                        </th>
                                        <th wire:click="sortBy('description')" scope="tw-col"
                                            class="tw-py-3.5 tw-pl-4 tw-pr-3 tw-text-left tw-text-sm tw-font-semibold tw-text-gray-900 sm:tw-pl-6 tw-cursor-pointer">
                                            Description
                                            @if ($this->order == 'asc' && $this->orderByColumn == 'description')
                                                <i class="fa fa-fw fa-sort-desc"></i>
                                            @elseif ($this->order == 'desc' && $this->orderByColumn == 'description')
                                                <i class="fa fa-fw fa-sort-asc"></i>
                                            @else
                                                <i class="fa fa-fw fa-sort"></i>
                                            @endif
                                            </span>
                                        </th>
                                        <th wire:click="sortBy('price')" scope="tw-col"
                                            class="tw-py-3.5 tw-pl-4 tw-pr-3 tw-text-left tw-text-sm tw-font-semibold tw-text-gray-900 sm:tw-pl-6 tw-cursor-pointer">
                                            Price
                                            @if ($this->order == 'asc' && $this->orderByColumn == 'price')
                                                <i class="fa fa-fw fa-sort-desc"></i>
                                            @elseif ($this->order == 'desc' && $this->orderByColumn == 'price')
                                                <i class="fa fa-fw fa-sort-asc"></i>
                                            @else
                                                <i class="fa fa-fw fa-sort"></i>
                                            @endif
                                            </span>
                                        </th>
                                    </tr>
                                </thead>
                                <tbody class="tw-divide-y tw-divide-gray-200 tw-bg-white">
                                    <tr>
                                        <td
                                            class="tw-whitespace-nowrap tw-py-4 tw-pl-4 tw-pr-3 tw-text-sm tw-font-medium tw-text-gray-900 sm:tw-pl-6">
                                            <input type="text" placeholder="Search..."
                                                class="tw-mt-2 tw-text-sm sm:tw-text-base tw-pl-2 tw-pr-4 tw-rounded-lg tw-border tw-border-gray-400 tw-w-full tw-py-1 focus:tw-outline-none focus:tw-border-blue-400"
                                                autocomplete="off" wire:model="searchColumns.title">
                                        </td>
                                        <td class="tw-whitespace-nowrap tw-px-3 tw-py-4 tw-text-sm tw-text-gray-500">
                                            <input type="text" placeholder="Search..."
                                                class="tw-mt-2 tw-text-sm sm:tw-text-base tw-pl-2 tw-pr-4 tw-rounded-lg tw-border tw-border-gray-400 tw-w-full tw-py-1 focus:tw-outline-none focus:tw-border-blue-400"
                                                autocomplete="off" wire:model="searchColumns.description">
                                        </td>
                                        <td class="tw-whitespace-nowrap tw-px-3 tw-py-4 tw-text-sm tw-text-gray-500">
                                            <label for="startingPrice">From</label>
                                            <input id="startingPrice" wire:model="searchColumns.price.startingPrice"
                                                type="number"
                                                class="tw-mt-2 tw-text-sm sm:tw-text-base tw-pl-2 tw-pr-4 tw-rounded-lg tw-border tw-border-gray-400 tw-w-full tw-py-1 focus:tw-outline-none focus:tw-border-blue-400"
                                                style="width: 70px">

                                            <label for="endingPrice">To</label>
                                            <input id="endingPrice" wire:model="searchColumns.price.endingPrice"
                                                type="number"
                                                class="tw-mt-2 tw-text-sm sm:tw-text-base tw-pl-2 tw-pr-4 tw-rounded-lg tw-border tw-border-gray-400 tw-w-full tw-py-1 focus:tw-outline-none focus:tw-border-blue-400"
                                                style="width: 70px">
                                        </td>
                                    </tr>

                                    @foreach ($this->dummyProducts as $product)
                                        <tr>
                                            <td
                                                class="tw-whitespace-nowrap tw-py-4 tw-pl-4 tw-pr-3 tw-text-sm tw-font-medium tw-text-gray-900 sm:tw-pl-6">
                                                {{ $product->title }}
                                            </td>
                                            <td
                                                class="tw-whitespace-nowrap tw-px-3 tw-py-4 tw-text-sm tw-text-gray-500">
                                                {{ $product->description ?? '' }}
                                            </td>
                                            <td
                                                class="tw-whitespace-nowrap tw-px-3 tw-py-4 tw-text-sm tw-text-gray-500">
                                                {{ $product->price ?? '' }}
                                            </td>
                                        </tr>
                                    @endforeach
                                </tbody>
                            </table>
                            <div class="tw-my-3">
                                {{ $this->dummyProducts->links() }}
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>