cakmalik/livewire-generic-table
Install the Package
composer require cakmalik/livewire-generic-table
Publish views if using Laravel < 10.21:
php artisan vendor:publish --tag=livewire-generic-table-views
Define Columns
Create a $columns array in your controller or Blade file. Example:
$columns = [
['label' => 'ID', 'field' => 'id', 'sortable' => true],
['label' => 'Name', 'field' => 'name', 'searchable' => true],
];
Render the Table Use the component in Blade:
<livewire:generic-table
:model="'App\Models\User'"
:columns="$columns"
defaultSortField="name"
defaultSortDirection="asc"
/>
Volt-Specific Setup For Volt, define columns as a computed property:
#[Computed]
public function columns(): array
{
return [
['label' => 'ID', 'field' => 'id'],
['label' => 'Email', 'field' => 'email'],
];
}
Dynamic Column Configuration
:columns prop to define table structure. Each column supports:
label: Display name.field: Model attribute or accessor.sortable: Enable sorting (default: false).searchable: Enable global search (default: false).renderer: Custom closure for cell formatting (e.g., badges, links).$columns = [
[
'label' => 'Status',
'field' => 'status',
'renderer' => fn($value) => "<span class='badge bg-$value'>$value</span>",
],
];
Query Parameter Handling
:queryParams to pre-filter results (e.g., search keywords, filters):
<livewire:generic-table
:model="'App\Models\Post'"
:columns="$columns"
:queryParams="['status' => 'published', 'keyword' => request('q')]"
/>
Row Actions
:actions prop (Volt: computed property):
$actions = [
'edit' => ['label' => 'Edit', 'icon' => 'edit'],
'delete' => ['label' => 'Delete', 'icon' => 'trash'],
];
$emit('action', $id, 'edit') in your Livewire class.Pagination
:perPageOptions:
<livewire:generic-table
:perPageOptions="[10, 25, 50]"
perPage="25"
/>
Integration with Volt
#[Computed]
public function columns(): array { ... }
#[Computed]
public function actions(): array { ... }
Custom Renderers: Use closures for complex cell formatting (e.g., avatars, status indicators):
'renderer' => fn($user) => view('partials.user-avatar', ['user' => $user]),
Conditional Columns: Dynamically toggle columns based on user roles or permissions:
$columns = auth()->user()->can('manage_users')
? array_merge($columns, [['field' => 'email', 'label' => 'Email']])
: $columns;
Bulk Actions: Extend the component to support bulk operations (e.g., select-all checkboxes) by overriding the table’s template or using slots.
API Integration: For headless tables, pass an API response as the model and customize the query builder logic in the Livewire class.
Volt Nested State Limitation:
public array props will fail.#[Computed]) for dynamic arrays.Case-Sensitive Field Matching:
field values against model attributes case-sensitively. Use accessors or normalize fields (e.g., snake_case) to avoid errors.Query Builder Overrides:
getTableQuery() is properly overridden to handle custom query logic (e.g., joins, scopes).Renderer Scope:
$model->relation.Pagination Conflicts:
cursor()), override getPagination() in your Livewire class to return the correct paginator.Check Column Definitions:
Validate your $columns array for typos in field names or missing required keys. Use dd($columns) to inspect the structure.
Query Logs: Enable Laravel query logging to verify the component’s SQL:
DB::enableQueryLog();
// ... run Livewire update ...
dd(DB::getQueryLog());
Event Emission: Ensure row actions emit events with the correct payload:
$this->emit('action', $id, 'edit'); // Format: event, id, action_name
View Publishing: If styles or views are missing, republish assets:
php artisan vendor:publish --tag=livewire-generic-table-views --force
Custom Templates: Override the default table view by publishing and modifying:
php artisan vendor:publish --tag=livewire-generic-table-views
Then extend the published resources/views/vendor/livewire-generic-table/table.blade.php.
Add New Renderer Types:
Extend the component by adding new renderer methods to the Livewire class (e.g., renderProgressBar()).
Localization:
Customize labels (e.g., "No results") by overriding the getTranslations() method or publishing the language file.
Headless Mode:
For SPAs or API-driven apps, disable the default table view and return data via $this->dispatch() or a custom event.
Testing: Use Livewire’s testing helpers to assert table behavior:
$this->assertSeeInOrder(['ID', 'Name'], $table);
$this->assertSelected('25', $table->perPageSelect);
How can I help you explore Laravel packages today?