Installation
composer require artflow-studio/table
The package auto-registers with Laravel (no manual service provider registration needed).
First Use Case: Basic Table
Create a Livewire component with the @AFtable directive:
// app/Livewire/UsersTable.php
use ArtflowStudio\Table\Traits\Table;
class UsersTable extends LivewireComponent
{
use Table;
public function table()
{
return User::query();
}
public function columns()
{
return [
'id' => 'ID',
'name' => 'Name',
'email' => 'Email',
];
}
}
Render it in a Blade view:
@AFtable('livewire:users-table')
Where to Look First
/aftable/generator for interactive docs and code snippets.Table trait and its methods (table(), columns(), filters()).vendor/artflow-studio/table/src/Examples directory for real-world usage patterns.Model-Based Tables
public function table()
{
return User::query()
->with(['posts' => fn($q) => $q->limit(1)]) // N+1 prevention
->when($this->search, fn($q) => $q->where('name', 'like', "%{$this->search}%"));
}
Static/Array Mode
public function table()
{
return collect([
['id' => 1, 'name' => 'John'],
['id' => 2, 'name' => 'Jane'],
]);
}
Column Customization
return ['name', 'email'];
return [
'name' => fn(User $user) => view('custom.name', ['user' => $user]),
'status' => fn(User $user) => "<span class='{$user->status_class}'>{$user->status}</span>",
];
return [
'full_name' => fn(User $user) => "{$user->first_name} {$user->last_name}",
];
Filters and Search
public function filters()
{
return [
'search' => ['type' => 'text', 'label' => 'Search'],
'status' => ['type' => 'select', 'label' => 'Status', 'options' => ['active', 'inactive']],
'date_range' => ['type' => 'dateRange', 'label' => 'Created At'],
];
}
Events and Actions
#[On('delete')]
public function deleteUser($id)
{
User::find($id)->delete();
$this->table->reset();
}
Blade:
@AFtable('livewire:users-table')
@column('actions')
<button wire:click="delete({{ $user->id }})">Delete</button>
@endcolumn
@endAFtable
Export Integration
public function export()
{
return $this->table->export('csv');
}
Blade:
<button wire:click="export">Export CSV</button>
theme() method to customize classes:
public function theme()
{
return [
'table' => 'bg-white border',
'th' => 'bg-gray-50',
'td' => 'px-4 py-2',
];
}
#[Computed] to cache queries:
#[Computed]
public function table()
{
return User::query()->paginate(10);
}
Table trait in a base component for shared logic:
class BaseTable extends LivewireComponent
{
use Table;
public function table()
{
return $this->model::query();
}
}
N+1 Queries
table() can cause performance issues.with() or loadMissing():
return User::with(['posts', 'comments'])->query();
Column Mismatch
columns() returns keys that don’t match the query results, the table may render incorrectly.fn() closures for dynamic or computed columns:
return ['full_name' => fn(User $user) => "{$user->first_name} {$user->last_name}"];
Livewire State Persistence
public $search;
public $status = 'active';
Blade Raw Output
{!! !!} in raw columns can lead to XSS vulnerabilities.|escape:
return ['description' => fn(User $user) => e($user->description)];
Generator Tool Limitations
/aftable/generator tool may not reflect all customizations (e.g., themes).theme() or columns().\DB::enableQueryLog();
$this->table->toBase()->get();
\Log::info(\DB::getQueryLog());
dd($this->all()) to inspect component state.Default Sorting
defaultSort():
public function defaultSort()
{
return ['name', 'asc'];
}
Pagination
perPage():
public function perPage()
{
return 20;
}
Export Formats
composer require barryvdh/laravel-snappy maatwebsite/excel
Custom Directives
Extend the @AFtable directive by publishing the package’s views:
php artisan vendor:publish --tag=aftable.views
Then modify resources/views/vendor/aftable/table.blade.php.
Hooks
Use Livewire’s #[On] events for custom logic:
#[On('tableInitialized')]
public function onTableInitialized()
{
// Run after table loads
}
Static Methods
Access the table instance via $this->table for advanced use cases:
#[On('rowClick')]
public function handleRowClick($row)
{
$this->table->setSelected($row['id']);
}
How can I help you explore Laravel packages today?