developerawam/livewire-datatable
Installation:
composer require developerawam/livewire-datatable
Publish config (optional):
php artisan vendor:publish --provider="Developerawam\LivewireDatatable\LivewireDatatableServiceProvider"
First Use Case:
use Developerawam\LivewireDatatable\LivewireDatatable;
use App\Models\User;
class UserTable extends LivewireDatatable
{
public $model = User::class;
}
Blade template:
<livewire:user-table />
config/livewire-datatable.php (for global defaults)resources/views/vendor/livewire-datatable directory for default templatesDefine the Table Class:
Extend LivewireDatatable and specify your model:
class PostTable extends LivewireDatatable
{
public $model = Post::class;
// Optional: Override defaults
public $perPage = 20;
}
Customize Columns:
public function columns()
{
return [
'id' => 'ID',
'title' => 'Title',
'published_at' => (new CarbonColumn('published_at'))
->format('Y-m-d'),
];
}
Add Filters:
public function filters()
{
return [
'published' => [
'type' => 'boolean',
'label' => 'Published',
],
'category' => [
'type' => 'select',
'label' => 'Category',
'options' => Category::pluck('name', 'id'),
],
];
}
Integrate with Views:
<livewire:post-table
:columns="$columns"
:filters="$filters"
/>
BaseAdminTable).column() method to conditionally include columns:
public function columns()
{
$columns = ['id', 'name'];
if (auth()->can('view-extra')) {
$columns[] = 'metadata';
}
return $columns;
}
getQuery() method to fetch data for external APIs:
public function getQuery()
{
return $this->model::query()
->where('active', true);
}
<livewire:post-table :wire:key="$this->editMode">
@include('tables.edit-modal')
</livewire:datatable>
datatable-updated):
protected $listeners = ['datatable-updated' => 'syncFilters'];
Livewire::test() with assertSeeInTable() helper methods.Query Performance:
select() in getQuery() to limit columns:
public function getQuery()
{
return $this->model::query()->select('id', 'name', 'email');
}
Relationship Loading:
with() in getQuery():
public function getQuery()
{
return $this->model::with('author')->query();
}
loadMissing() or constrain().Configuration Overrides:
public $perPage = ... is defined before columns()/filters():
public $perPage = 50; // Must come first
Caching Headers:
wire:key dynamically or use wire:ignore for static parts.config/livewire-datatable.php:
'debug' => [
'query_logging' => true,
],
dd($this->emit('alert', 'Debug info')) to inspect state.dd($this->request) in mount() to see incoming data.Custom Columns:
Developerawam\LivewireDatatable\Column for reusable column types:
class StatusColumn extends Column
{
public function render($value)
{
return view('tables.status-badge', ['status' => $value]);
}
}
Custom Actions:
actions() method:
public function actions()
{
return [
'edit' => 'Edit',
'delete' => 'Delete',
];
}
handleAction():
public function handleAction($action, $id)
{
if ($action === 'delete') {
$this->model::find($id)->delete();
}
}
Bulk Actions:
bulkActions() for multi-row operations:
public function bulkActions()
{
return [
'export' => 'Export Selected',
'delete' => 'Delete Selected',
];
}
handleBulkAction():
public function handleBulkAction($action, $ids)
{
if ($action === 'delete') {
$this->model::whereIn('id', $ids)->delete();
}
}
Custom Templates:
php artisan vendor:publish --tag=livewire-datatable-views
resources/views/vendor/livewire-datatable/table.blade.php.lazy property to defer table initialization:
<livewire:post-table :lazy="true" />
public function mount()
{
$this->perPage = auth()->user()->isAdmin() ? 100 : 20;
}
'labels' => [
'search' => __('Search'),
'per_page' => __('Items per page'),
],
public function mount()
{
$this->authorize('view', $this->model);
}
How can I help you explore Laravel packages today?