Installation:
composer require mediconesystems/livewire-datatables
For Laravel 9, also run:
composer require psr/simple-cache:^1.0 maatwebsite/excel
Publish Assets (if needed):
php artisan vendor:publish --provider="MedicOneSystems\LivewireDatatable\LivewireDatatableServiceProvider"
Basic Usage: Create a Livewire component:
php artisan make:livewire Admin/UserTable
Define Datatable in Component:
use MedicOneSystems\LivewireDatatable\LivewireDatatable;
public function datatable()
{
return LivewireDatatable::create()
->setModel(User::class)
->addColumn('name')
->addColumn('email')
->setPrimaryKey('id')
->setSearch(['name', 'email']);
}
Render in Blade:
<livewire:admin.user-table />
Build a user management table with search, sorting, and pagination:
public function datatable()
{
return LivewireDatatable::create()
->setModel(User::class)
->addColumn('name')
->addColumn('email')
->addColumn('created_at', 'Date')
->setPrimaryKey('id')
->setSearch(['name', 'email'])
->setPerPage(10);
}
setModel() to bind to an Eloquent model.
->setModel(User::class)
setQuery() for raw queries.
->setQuery(User::where('active', 1))
->addColumn('name')
->addColumn('email')
->addColumn('name', 'Name', function ($value) {
return ucfirst($value);
})
->addColumn('full_name', 'Full Name', function ($row) {
return $row->first_name . ' ' . $row->last_name;
})
->setSearch(['name', 'email'])
->addBooleanFilter('active')
->addDateFilter('created_at')
->addSelectFilter('role', ['admin', 'user', 'moderator'])
->setDefaultSort('name', 'asc')
->addSort('full_name', 'Full Name')
->setPerPage(20)
->addBulkAction('Delete', 'deleteSelected', 'danger')
public function deleteSelected()
{
User::whereIn('id', $this->getSelected())->delete();
}
->addColumnGroup('Contact', [
'email',
'phone',
])
->addExport('CSV')
->addExport('Excel')
// UserTable.php
public function datatable()
{
return LivewireDatatable::create()
->setModel(User::class)
->addColumn('name')
->addColumn('email')
->addColumn('created_at', 'Date')
->setPrimaryKey('id')
->setSearch(['name', 'email'])
->setPerPage(10);
}
public function deleteSelected()
{
User::whereIn('id', $this->getSelected())->delete();
session()->flash('message', 'Users deleted successfully.');
}
<div>
@if (session()->has('message'))
<div class="mb-4 p-4 bg-green-100 text-green-800">
{{ session('message') }}
</div>
@endif
<livewire:admin.user-table />
</div>
For advanced filtering (e.g., combined conditions):
public function datatable()
{
return LivewireDatatable::create()
->setModel(User::class)
->addColumn('name')
->addColumn('email')
->setQuery(function ($query) {
return $query->where('active', true)
->whereHas('roles', function ($q) {
$q->where('name', 'admin');
});
});
}
Tailwind/Alpine Dependencies:
tailwindcss and alpinejs are properly installed and configured.resources/js/app.js for Alpine initialization:
import Alpine from 'alpinejs';
window.Alpine = Alpine;
Alpine.start();
Model vs. Query Builder:
setQuery(), ensure the query returns the expected columns (or use addColumn with callbacks).setModel() and setQuery() in the same datatable.Primary Key Mismatch:
setPrimaryKey() is omitted, the datatable defaults to id. Ensure this matches your model’s primary key.Bulk Actions:
$this->getSelected() to avoid SQL errors:
if (!$this->getSelected()) {
session()->flash('error', 'No items selected.');
return;
}
Performance with Large Datasets:
setPerPage() to limit initial load size.Column Naming Conflicts:
created_at), use aliases:
->addColumn('created_at', 'Date Created')
Query Logs: Enable Laravel query logging to inspect generated SQL:
\DB::enableQueryLog();
$this->datatable()->getQuery()->toSql();
dd(\DB::getQueryLog());
Livewire Hooks:
Use mount() or updated() to debug component state:
public function mount()
{
\Log::info('Datatable mounted', $this->datatable()->getQuery()->toSql());
}
Alpine/JS Issues:
Reusable Datatables: Create a base component for shared functionality:
// BaseDatatable.php
public function configure()
{
return LivewireDatatable::create()
->setPerPage(15)
->setSearch(['name', 'email'])
->addExport('CSV');
}
Dynamic Columns: Load columns dynamically based on user roles:
if (auth()->user()->isAdmin()) {
$datatable->addColumn('deleted_at', 'Deleted At');
}
Custom Filters: Extend the filter system with custom logic:
->addFilter('custom_filter', function ($query, $value) {
return $query->where('status', $value);
})
Tailwind Styling: Override default styles by publishing the config:
php artisan vendor:publish --tag=livewire-datatables-config
Then customize resources/css/livewire-datatables.css.
Localization: Use Laravel’s localization features for filter labels:
->addSelectFilter('role', ['admin', 'user'], function () {
return [
'admin' => __('Admin'),
'user' => __('User'),
];
})
Testing: Use Livewire’s testing helpers to assert datatable behavior:
$this->livewire(UserTable::class)
->assertDispatchedBrowserEvent('datatable-updated');
Caching: For static data, cache the query result:
->setQuery(function ($query) {
return cache()->remember('users.datatable', now()->addHours(1), function () {
How can I help you explore Laravel packages today?