Install the Package
composer require tiagospem/simple-tables
php artisan st:install
Generate a Table Component
php artisan st:create table UsersTable
This creates a Livewire component at app/Livewire/UsersTable.php.
Define Columns
In UsersTable.php, use the columns() method to define table columns:
public function columns(): array
{
return [
Column::make('Name', 'name'),
Column::make('Email', 'email')
->sortable()
->searchable(),
];
}
Set the Data Source
Override query() to return an Eloquent query builder:
public function query(): Builder
{
return User::query();
}
Render the Table Add the component to a Blade view:
@livewire('users-table')
columns() to display model attributes.actions():
public function actions(): array
{
return [
Column::action('Edit', 'edit')
->icon('edit')
->url(fn ($row) => route('users.edit', $row)),
];
}
Data Binding
query() to bind an Eloquent query. The package handles pagination, sorting, and filtering automatically.public function query(): Builder
{
return User::with('roles')->query();
}
Column Customization
->sortable() to enable column sorting.->searchable() to enable global or column-specific search.->format(fn ($value) => ...) to customize cell rendering.
Column::make('Status', 'status')
->format(fn ($status) => $status === 'active' ? 'Active' : 'Inactive')
Filters
filters():
public function filters(): array
{
return [
Column::filter('Role')
->select([
'admin' => 'Admin',
'user' => 'User',
]),
];
}
->dependsOn() for dependent filters:
Column::filter('Sub Role')
->select(fn ($query) => $query->where('role_id', $this->role))
->dependsOn('role')
Row Actions
actions():
public function actions(): array
{
return [
Column::action('Delete', 'delete')
->icon('trash')
->confirmation('Are you sure?')
->method('destroy'),
];
}
->url() for external links or ->method() for Livewire methods.Bulk Actions
bulkActions():
public function bulkActions(): array
{
return [
Column::bulkAction('Delete Selected', 'deleteSelected')
->icon('trash')
->confirmation('Are you sure?'),
];
}
public function deleteSelected()
{
$this->selectedRows()->each->delete();
}
Row Details
details():
public function details(): array
{
return [
Column::detail('User Details')
->content(fn ($row) => view('livewire.users.details', ['user' => $row])),
];
}
public function query(): Builder
{
return User::search($this->search)->query();
}
protected $listeners = ['refreshTable' => '$refresh'];
public function updatedSearch()
{
$this->resetPage();
}
resources/css/app.css or use the theme() method:
public function theme(): string
{
return 'dark'; // or custom theme
}
Query Caching
query(); let the package handle pagination and filtering dynamically.private $users;
public function query(): Builder { return $this->users ??= User::all(); }
public function query(): Builder { return User::query(); }
Relationship Loading
query() to avoid N+1 queries:
public function query(): Builder
{
return User::with('posts')->query();
}
Column::make('Post Count', fn ($row) => $row->posts->count())
Filter Persistence
public function resetFilters()
{
$this->reset(['role', 'search']);
}
Livewire Property Binding
public $property syntax:
public $role;
private $role;
Action Confirmation
->confirmation() for destructive actions to avoid accidental triggers:
Column::action('Delete', 'delete')
->confirmation('This action cannot be undone.')
Default Sorting
query():
public function query(): Builder
{
return User::query()->orderBy('name');
}
->defaultSort() in columns:
Column::make('Name', 'name')->defaultSort()
Pagination
public function pagination(): int
{
return 25; // Default is 10
}
public function pagination(): bool
{
return false;
}
Search Behavior
->searchable().->searchable()->global(false).Custom Columns
TiagoSpem\SimpleTables\Column for reusable column types:
class StatusColumn extends Column
{
public function format($value)
{
return $value === 'active' ? 'Active' : 'Inactive';
}
}
StatusColumn::make('Status', 'status')
Custom Filters
TiagoSpem\SimpleTables\Filter:
class RoleFilter extends Filter
{
public function apply(Builder $query)
{
return $query->where('role_id', $this->value);
}
}
RoleFilter::make('Role')
->select(['admin' => 'Admin', 'user' => 'User'])
Custom Themes
public function theme(): string
{
return 'custom-theme';
}
resources/css/custom-theme.css.Event Listeners
protected $listeners = [
'tableRowSelected' => 'handleRowSelected',
];
public function handleRowSelected($row)
{
// Custom logic
}
API Integration
getData():
public function getData(): array
{
return Http::get('api/users')->json();
}
How can I help you explore Laravel packages today?