idkwhoami / flux-tables
This package provides a reusable, configurable table livewire component styled using Flux
Requires
- php: ^8.3
- livewire/flux: ^2.0
- livewire/flux-pro: ^2.0
Requires (Dev)
- illuminate/support: ^11.41
- larastan/larastan: ^2.9
- laravel/pint: ^1.20
- nunomaduro/collision: ^8.1.1||^7.10.0
- orchestra/testbench: ^9.9
- pestphp/pest: ^3.7
- pestphp/pest-plugin-arch: ^3.0
- pestphp/pest-plugin-laravel: ^3.1
- phpstan/extension-installer: ^1.3
- phpstan/phpstan: ^1.12
- phpstan/phpstan-deprecation-rules: ^1.1
- phpstan/phpstan-phpunit: ^1.3
This package is auto-updated.
Last update: 2025-07-09 09:29:17 UTC
README
A comprehensive Laravel Livewire table component package built on top of Flux UI that provides a modular, customizable way to create data tables with advanced features like filtering, sorting, searching, and PostgreSQL-specific functionality.
Important
This package is NOT "in development". If I need to extend it i will do so. Feel free to fork it or use it as is. But feature requests are probably being ignored. Same for pull requests
Warning
This package is meant to be used in combination with a PostgreSQL database as it provides utils that most databases dont have. For example json path walking & vectors.
What This Package Does
Flux Tables provides a complete table solution for Laravel applications with:
- Modular Architecture: Use traits to build custom table components with only the features you need
- Rich Column Types: Text, DateTime, Boolean, JSON, Component, Action, and List columns
- Advanced Filtering: Boolean, Date Range, Select, Value Present, and Deleted filters with session persistence
- PostgreSQL Features: JSON path querying, advanced sorting, and database-specific optimizations
- Livewire Integration: Reactive components with real-time updates and state management
- Flux UI Integration: Beautiful, accessible UI components out of the box
How It's Meant to Be Used
The package offers two main approaches:
- Quick Setup: Use the pre-built
SimpleTable
component for rapid development - Custom Components: Build your own table components using the modular trait system
The modular design allows you to pick and choose features:
HasEloquentTable
- Core Eloquent query functionalityHasFilters
- Filter management and applicationHasSorting
- Column sorting with PostgreSQL JSON supportHasSearch
- Global search functionalityHasActions
- Row-level actions (edit, delete, etc.)HasToggleableColumns
- Show/hide columnsHasDynamicPagination
- Configurable pagination
Installation
You can install the package via composer:
composer require idkwhoami/flux-tables
Run the installation command:
php artisan flux-tables:install
This will use the flux:icon
artisan command to fetch the Lucide icons used in the package.
Quick Start
Here's a basic example using the pre-built SimpleTable component:
$filters = [ \Idkwhoami\FluxTables\Concretes\Filter\DeletedFilter::make('deleted') ->label('Deletion State') ->default(\Idkwhoami\FluxTables\Enums\DeletionState::WithoutDeleted->value), \Idkwhoami\FluxTables\Concretes\Filter\DateRangeFilter::make('created') ->property('created_at') ->label('Created'), \Idkwhoami\FluxTables\Concretes\Filter\ValuePresentFilter::make('email_verified') ->property('email_verified_at') ->label('Exclude unverified') ->description('Hide all users that haven\'t verified their email address.') ->pillContent('Unverified excluded'), \Idkwhoami\FluxTables\Concretes\Filter\BooleanFilter::make('banned') ->property('banned'), ]; $columns = [ \Idkwhoami\FluxTables\Concretes\Column\ComponentColumn::make('name') ->label('Username') ->sortable() ->searchable() ->component('columns.user-name-input') ->property('name'), \Idkwhoami\FluxTables\Concretes\Column\DatetimeColumn::make('created') ->humanReadable() ->label("Created") ->sortable() ->property('created_at'), \Idkwhoami\FluxTables\Concretes\Column\TextColumn::make('posts') ->count() ->label('Posts') ->relation('posts') ->property('posts_count'), \Idkwhoami\FluxTables\Concretes\Column\DatetimeColumn::make('email_verified') ->label("Email Verified At") ->sortable() ->property('email_verified_at'), \Idkwhoami\FluxTables\Concretes\Column\BooleanColumn::make('banned') ->label('Banned') ->property('banned'), \Idkwhoami\FluxTables\Concretes\Column\DatetimeColumn::make('deleted') ->label("Deleted") ->default('n/a') ->property('deleted_at'), \Idkwhoami\FluxTables\Concretes\Column\ActionColumn::make('actions') ->actions([ Idkwhoami\FluxTables\Abstracts\Action\ModalAction::make('open') ->label('Open') ->icon('arrow-top-right-on-square') ->link() ->component('user-delete-confirmation'), Idkwhoami\FluxTables\Abstracts\Action\DirectAction::make('delete') ->visible(fn(\Illuminate\Database\Eloquent\Model $model) => auth()->user()->isNot($model) && !$model->deleted_at) ->label('Delete') ->icon('trash-2') ->operation(\Idkwhoami\FluxTables\Concretes\Operation\DeleteOperation::make('delete')), Idkwhoami\FluxTables\Abstracts\Action\DirectAction::make('restore') ->visible(fn(\Illuminate\Database\Eloquent\Model $model) => auth()->user()->isNot($model) && $model->deleted_at) ->label('Restore') ->icon('rotate-ccw') ->operation(\Idkwhoami\FluxTables\Concretes\Operation\RestoreOperation::make('restore')), ]), ];
<livewire:flux-simple-table create="user-create-form" title="Users" :model="\App\Models\User::class" :default-toggled-columns="['created']" :$filters :$columns />
API Documentation
Abstract Classes
Action (Idkwhoami\FluxTables\Abstracts\Action\Action
)
Base class for all table actions.
Methods:
label(string $label): static
- Set the action labelicon(string $icon): static
- Set the action icon (Lucide icon name)variant(?string $variant): static
- Set the action variant (default, danger, outline, filled, primary, ghost, subtle)visible(Closure|bool $visible): static
- Set visibility conditionaccess(Closure|bool $access): static
- Set access control conditionlink(bool $link = true): static
- Render as link instead of buttonrender(mixed $id): string|HtmlString|View|null
- Abstract method to render the action
Column (Idkwhoami\FluxTables\Abstracts\Column\Column
)
Base class for all table columns.
Methods:
label(?string $label): static
- Set the column labelsortable(bool $sortable = true): static
- Make column sortablesearchable(bool $searchable = true): static
- Make column searchabletoggleable(bool $toggleable): static
- Make column toggleablevisible(bool|Closure $visible = true): static
- Set visibility conditionrender(object $value): string|HtmlString|View|null
- Abstract method to render the column
PropertyColumn (Idkwhoami\FluxTables\Abstracts\Column\PropertyColumn
)
Extends Column for property-based columns.
Methods:
property(string $property): static
- Set the model propertyrelation(string $relation): static
- Set the relation namecount(bool $count = true): static
- Count relation itemsdefault(mixed $default): static
- Set default valuetransform(Closure $transform): static
- Transform the value before rendering
Filter (Idkwhoami\FluxTables\Abstracts\Filter\Filter
)
Base class for all table filters.
Methods:
label(string $label): static
- Set the filter labeldefault(mixed $default): static
- Set default valuevisible(Closure|bool $visible): static
- Set visibility conditionapply(Builder $query): void
- Abstract method to apply filter to querycomponent(): string
- Abstract method to return Livewire component namerenderPill(): string|HtmlString|View
- Abstract method to render filter pill
Table (Idkwhoami\FluxTables\Abstracts\Table\Table
)
Base class for table configuration.
Methods:
columns(array $columns): static
- Set table columnsfilters(array $filters): static
- Set table filtersgetColumns(): array
- Get visible columnsgetFilters(): array
- Get visible filtersgetColumn(string $key): Column
- Get specific column by key
Concrete Column Implementations
TextColumn (Idkwhoami\FluxTables\Concretes\Column\TextColumn
)
Simple text column for displaying string values.
DatetimeColumn (Idkwhoami\FluxTables\Concretes\Column\DatetimeColumn
)
Column for displaying dates and times.
Methods:
format(string $format): static
- Set date format (default: 'm/d/Y H:i:s')humanReadable(bool $readable = true): static
- Display as human-readable format (e.g., "2 hours ago")
BooleanColumn (Idkwhoami\FluxTables\Concretes\Column\BooleanColumn
)
Column for displaying boolean values as badges or icons.
JsonColumn (Idkwhoami\FluxTables\Concretes\Column\JsonColumn
)
PostgreSQL-specific column for querying JSON data.
Methods:
path(array|string $path): static
- Set JSON path (e.g., 'user.name' or ['user', 'name'])type(JsonPropertyType $type): static
- Set PostgreSQL cast type (text, integer, boolean, etc.)
ComponentColumn (Idkwhoami\FluxTables\Concretes\Column\ComponentColumn
)
Column that renders a custom Blade component.
Methods:
component(string $component): static
- Set the component name
ActionColumn (Idkwhoami\FluxTables\Concretes\Column\ActionColumn
)
Column for displaying row actions.
Methods:
actions(array $actions): static
- Set the actions array
ListColumn (Idkwhoami\FluxTables\Concretes\Column\ListColumn
)
Column for displaying arrays or collections as lists.
Concrete Filter Implementations
BooleanFilter (Idkwhoami\FluxTables\Concretes\Filter\BooleanFilter
)
Filter for boolean values with true/false/all options.
DateRangeFilter (Idkwhoami\FluxTables\Concretes\Filter\DateRangeFilter
)
Filter for date ranges with start and end date inputs.
Methods:
property(string $property): static
- Set the date property to filter
DeletedFilter (Idkwhoami\FluxTables\Concretes\Filter\DeletedFilter
)
Filter for soft-deleted models with options for all/only deleted/without deleted.
SelectFilter (Idkwhoami\FluxTables\Concretes\Filter\SelectFilter
)
Filter with predefined options in a select dropdown.
Methods:
options(array $options): static
- Set the available options
ValuePresentFilter (Idkwhoami\FluxTables\Concretes\Filter\ValuePresentFilter
)
Filter to show/hide records based on whether a field has a value.
Methods:
property(string $property): static
- Set the property to checkdescription(string $description): static
- Set filter descriptionpillContent(string $content): static
- Set the pill display text
Action Implementations
DirectAction (Idkwhoami\FluxTables\Abstracts\Action\DirectAction
)
Action that executes immediately when clicked.
Methods:
operation(Operation $operation): static
- Set the operation to execute
ModalAction (Idkwhoami\FluxTables\Abstracts\Action\ModalAction
)
Action that opens a modal component.
Methods:
component(string $component): static
- Set the modal component name
Operations
DeleteOperation (Idkwhoami\FluxTables\Concretes\Operation\DeleteOperation
)
Operation for soft-deleting models.
RestoreOperation (Idkwhoami\FluxTables\Concretes\Operation\RestoreOperation
)
Operation for restoring soft-deleted models.
RouteOperation (Idkwhoami\FluxTables\Concretes\Operation\RouteOperation
)
Operation for redirecting to a route.
Methods:
route(string $route): static
- Set the route nameparameters(array $parameters): static
- Set route parameters
Traits for Custom Components
HasEloquentTable
Core trait for Eloquent-based tables.
Methods:
table(string $model, array $columns, array $filters): Table
- Configure the tablegetQuery(): Builder
- Get the base queryoptimizeSelects(bool $optimize): static
- Enable/disable select optimizationapplyRelations(Builder $query): void
- Apply relation joinsapplyColumns(Builder $query): void
- Apply column selections
HasFilters
Adds filtering functionality.
Methods:
applyFilters(Builder $query): void
- Apply active filters to querygetFilters(): array
- Get all filtersgetActiveFilters(): array
- Get currently active filtersresetFilter(string $filter): void
- Reset specific filterresetFilters(): void
- Reset all filtershasActiveFilters(): bool
- Check if any filters are active
HasSorting
Adds sorting functionality with PostgreSQL JSON support.
Properties:
?string $sortingColumn
- Current sort column?string $sortingDirection
- Current sort direction
Methods:
applySorting(Builder $query): void
- Apply sorting to querysort(string $column): void
- Sort by column (cycles through asc/desc/none)resetSorting(): void
- Reset sortinggetSortingColumn(): string
- Get current sort columngetSortingDirection(): string
- Get current sort directiondefaultSortingColumn(): string
- Default sort columndefaultSortingDirection(): string
- Default sort direction
HasSearch
Adds global search functionality.
Properties:
string $search
- Current search term
Methods:
applySearch(Builder $query): void
- Apply search to queryresetSearch(): void
- Clear search
HasActions
Adds row-level actions functionality.
Methods:
getActions(): array
- Get all actionsexecuteAction(string $action, mixed $id): void
- Execute an action
HasToggleableColumns
Adds column visibility toggling.
Methods:
toggleColumn(string $column): void
- Toggle column visibilitygetToggledColumns(): array
- Get currently visible columnsdefaultToggledColumns(): array
- Default visible columns
HasDynamicPagination
Adds configurable pagination.
Methods:
getPaginationOptions(): array
- Get pagination size optionsdefaultPaginationValue(): int
- Get default pagination size
Enums
DeletionState (Idkwhoami\FluxTables\Enums\DeletionState
)
All
- Show all recordsOnlyDeleted
- Show only soft-deleted recordsWithoutDeleted
- Show only non-deleted records
JsonPropertyType (Idkwhoami\FluxTables\Enums\JsonPropertyType
)
PostgreSQL cast types for JSON properties:
Text
- Cast as textInteger
- Cast as integerBoolean
- Cast as booleanNumeric
- Cast as numeric
Livewire Components
SimpleTable (Idkwhoami\FluxTables\Livewire\SimpleTable
)
Pre-built table component with all features enabled.
Properties:
string $title
- Table titlestring $model
- Eloquent model classarray $columns
- Column definitionsarray $filters
- Filter definitions?string $create
- Create component namearray $defaultToggledColumns
- Initially visible columns
Custom Table Example
Here's how to create a custom table component using the modular trait system. This example demonstrates building a comprehensive table with all available features:
1. Create the Livewire Component
<?php namespace App\Livewire; use App\Models\User; use Idkwhoami\FluxTables\Abstracts\Table\Table; use Idkwhoami\FluxTables\Concretes\Table\EloquentTable; use Idkwhoami\FluxTables\Traits\HasEloquentTable; use Idkwhoami\FluxTables\Traits\HasFilters; use Idkwhoami\FluxTables\Traits\HasSearch; use Idkwhoami\FluxTables\Traits\HasSorting; use Idkwhoami\FluxTables\Traits\HasActions; use Idkwhoami\FluxTables\Traits\HasToggleableColumns; use Idkwhoami\FluxTables\Traits\HasDynamicPagination; use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Contracts\Pagination\LengthAwarePaginator; use Illuminate\Contracts\View\View; use Livewire\Attributes\Computed; use Livewire\Component; use Livewire\WithPagination; class CustomUserTable extends Component { use HasEloquentTable; use HasFilters; use HasSorting; use HasSearch; use HasActions; use HasToggleableColumns; use HasDynamicPagination; use WithPagination; public string $search = ''; public function mount(): void { // Livewire automatically calls trait mount methods // No manual initialization needed } public function render(): View { return view('livewire.custom-user-table'); } #[Computed] public function models(): LengthAwarePaginator { return $this->getQuery()->paginate($this->getPaginationValue()); } public function getQuery(): Builder { $query = User::query(); // Apply the modular functionality $this->applySearch($query); $this->applyFilters($query); $this->applySorting($query); $this->applyRelations($query); $this->applyColumns($query); return $query; } protected function getColumns(): array { return [ \Idkwhoami\FluxTables\Concretes\Column\TextColumn::make('name') ->label('Name') ->property('name') ->searchable() ->sortable(), \Idkwhoami\FluxTables\Concretes\Column\TextColumn::make('email') ->label('Email') ->property('email') ->searchable() ->sortable(), \Idkwhoami\FluxTables\Concretes\Column\ComponentColumn::make('avatar') ->label('Avatar') ->component('columns.user-avatar') ->property('avatar_url') ->toggleable(false), // Always visible \Idkwhoami\FluxTables\Concretes\Column\TextColumn::make('posts') ->count() ->label('Posts') ->relation('posts') ->property('posts_count') ->sortable(), \Idkwhoami\FluxTables\Concretes\Column\DatetimeColumn::make('created_at') ->label('Created') ->property('created_at') ->humanReadable() ->sortable(), \Idkwhoami\FluxTables\Concretes\Column\DatetimeColumn::make('email_verified_at') ->label('Email Verified') ->property('email_verified_at') ->default('Not verified') ->sortable(), \Idkwhoami\FluxTables\Concretes\Column\BooleanColumn::make('banned') ->label('Banned') ->property('banned') ->sortable(), \Idkwhoami\FluxTables\Concretes\Column\JsonColumn::make('preferences') ->label('Theme') ->property('preferences') ->path(['ui', 'theme']) ->type(\Idkwhoami\FluxTables\Enums\JsonPropertyType::Text) ->default('default'), \Idkwhoami\FluxTables\Concretes\Column\DatetimeColumn::make('deleted_at') ->label('Deleted') ->property('deleted_at') ->default('n/a') ->sortable(), \Idkwhoami\FluxTables\Concretes\Column\ActionColumn::make('actions') ->label('Actions') ->actions([ \Idkwhoami\FluxTables\Abstracts\Action\ModalAction::make('edit') ->label('Edit') ->icon('pencil') ->link() ->component('user-edit-modal'), \Idkwhoami\FluxTables\Abstracts\Action\ModalAction::make('view') ->label('View Details') ->icon('eye') ->variant('outline') ->component('user-details-modal'), \Idkwhoami\FluxTables\Abstracts\Action\DirectAction::make('ban') ->visible(fn(\Illuminate\Database\Eloquent\Model $model) => auth()->user()->isNot($model) && !$model->banned && !$model->deleted_at) ->label('Ban') ->icon('user-x') ->variant('danger') ->operation(\Idkwhoami\FluxTables\Concretes\Operation\RouteOperation::make('ban') ->route('admin.users.ban') ->parameters(['user' => fn($model) => $model->id])), \Idkwhoami\FluxTables\Abstracts\Action\DirectAction::make('delete') ->visible(fn(\Illuminate\Database\Eloquent\Model $model) => auth()->user()->isNot($model) && !$model->deleted_at) ->label('Delete') ->icon('trash-2') ->variant('danger') ->operation(\Idkwhoami\FluxTables\Concretes\Operation\DeleteOperation::make('delete')), \Idkwhoami\FluxTables\Abstracts\Action\DirectAction::make('restore') ->visible(fn(\Illuminate\Database\Eloquent\Model $model) => auth()->user()->isNot($model) && $model->deleted_at) ->label('Restore') ->icon('rotate-ccw') ->operation(\Idkwhoami\FluxTables\Concretes\Operation\RestoreOperation::make('restore')), ]), ]; } protected function getFilters(): array { return [ \Idkwhoami\FluxTables\Concretes\Filter\DeletedFilter::make('deleted') ->label('Deletion State') ->default(\Idkwhoami\FluxTables\Enums\DeletionState::WithoutDeleted->value), \Idkwhoami\FluxTables\Concretes\Filter\ValuePresentFilter::make('verified') ->label('Email Verified') ->property('email_verified_at') ->description('Show only verified users') ->pillContent('Verified only'), \Idkwhoami\FluxTables\Concretes\Filter\BooleanFilter::make('banned') ->label('Banned Status') ->property('banned'), \Idkwhoami\FluxTables\Concretes\Filter\DateRangeFilter::make('created') ->label('Registration Date') ->property('created_at'), \Idkwhoami\FluxTables\Concretes\Filter\SelectFilter::make('role') ->label('User Role') ->property('role') ->options([ 'admin' => 'Administrator', 'moderator' => 'Moderator', 'user' => 'Regular User', ]), ]; } // Required by HasSorting trait public function defaultSortingColumn(): string { return 'created_at'; } public function defaultSortingDirection(): string { return 'desc'; } // Required by HasToggleableColumns trait public function defaultToggledColumns(): array { return ['name', 'email', 'created_at', 'actions']; // Default visible columns } // Required by HasDynamicPagination trait public function defaultPaginationValue(): int { return 15; } public function getPaginationOptions(): array { return [10, 15, 25, 50, 100]; } }
2. Create the Blade View
Create resources/views/livewire/custom-user-table.blade.php
:
<div class="space-y-4"> {{-- Header with title, search, filters, and controls --}} <div class="flex items-center justify-between"> <h2 class="text-xl font-semibold">Users Management</h2> <div class="flex items-center space-x-3"> {{-- Search Input --}} <div class="w-64"> <flux:input wire:model.live.debounce.300ms="search" placeholder="Search users..." icon="search" clearable /> </div> {{-- Pagination Size Selector --}} <flux:select wire:model.live="paginationValue" placeholder="Per page" class="w-24" > @foreach($this->getPaginationOptions() as $option) <flux:option value="{{ $option }}">{{ $option }}</flux:option> @endforeach </flux:select> {{-- Column Toggle Button --}} <flux:modal.trigger name="columns-modal"> <flux:button variant="outline" icon="columns"> Columns </flux:button> </flux:modal.trigger> {{-- Filter Button --}} @if($this->table->hasFilters()) <flux:modal.trigger name="filters-modal"> <flux:button variant="outline" icon="filter"> Filters @if($this->hasActiveFilters()) <flux:badge size="sm" color="blue">{{ count($this->getActiveFilters()) }}</flux:badge> @endif </flux:button> </flux:modal.trigger> @endif {{-- Create User Button --}} <flux:modal.trigger name="create-user-modal"> <flux:button icon="plus"> Add User </flux:button> </flux:modal.trigger> </div> </div> {{-- Active Filter Pills --}} @if($this->hasActiveFilters()) <div class="flex flex-wrap gap-2"> @foreach($this->getActiveFilters() as $filter) <flux:badge color="blue" size="sm" wire:click="resetFilter('{{ $filter->getName() }}')" class="cursor-pointer hover:bg-blue-600" > {{ $filter->renderPill() }} <flux:icon.x-mark class="w-3 h-3 ml-1" /> </flux:badge> @endforeach <flux:button variant="ghost" size="sm" wire:click="resetFilters" class="text-gray-500 hover:text-gray-700" > Clear all filters </flux:button> </div> @endif {{-- Table --}} <flux:table :paginate="$this->models"> <flux:columns> @foreach($this->getToggledColumns() as $column) <flux:column :sortable="$column->isSortable()" :sorted="$this->getSortingColumn() === $column->getName() ? $this->getSortingDirection() : null" wire:click="sort('{{ $column->getName() }}')" class="cursor-pointer hover:bg-gray-50" > <div class="flex items-center space-x-1"> <span>{{ $column->getLabel() }}</span> @if($column->isSortable()) @if($this->getSortingColumn() === $column->getName()) @if($this->getSortingDirection() === 'asc') <flux:icon.chevron-up class="w-4 h-4" /> @else <flux:icon.chevron-down class="w-4 h-4" /> @endif @else <flux:icon.chevron-up-down class="w-4 h-4 text-gray-400" /> @endif @endif </div> </flux:column> @endforeach </flux:columns> <flux:rows> @foreach($this->models as $user) <flux:row :key="$user->id" class="hover:bg-gray-50"> @foreach($this->getToggledColumns() as $column) <flux:cell> {!! $column->render($user) !!} </flux:cell> @endforeach </flux:row> @endforeach </flux:rows> </flux:table> {{-- Column Toggle Modal --}} <flux:modal name="columns-modal" class="md:w-96"> <div class="space-y-6"> <div> <flux:heading size="lg">Toggle Columns</flux:heading> <flux:subheading>Show or hide table columns</flux:subheading> </div> <div class="space-y-3"> @foreach($this->table->getColumns() as $column) @if($column->isToggleable()) <flux:checkbox wire:model.live="toggledColumns.{{ $column->getName() }}" label="{{ $column->getLabel() }}" /> @endif @endforeach </div> <div class="flex justify-end space-x-2"> <flux:modal.close> <flux:button variant="ghost">Close</flux:button> </flux:modal.close> </div> </div> </flux:modal> {{-- Filter Modal --}} @if($this->table->hasFilters()) <flux:modal name="filters-modal" class="md:w-96"> <div class="space-y-6"> <div> <flux:heading size="lg">Filters</flux:heading> <flux:subheading>Refine your search results</flux:subheading> </div> @foreach($this->getFilters() as $filter) <div> <livewire:dynamic-component :component="$filter->component()" :filter="$filter" :key="$filter->getName()" /> </div> @endforeach <div class="flex justify-end space-x-2"> <flux:modal.close> <flux:button variant="ghost">Close</flux:button> </flux:modal.close> <flux:button wire:click="resetFilters" variant="danger"> Clear All Filters </flux:button> </div> </div> </flux:modal> @endif {{-- Create User Modal (placeholder) --}} <flux:modal name="create-user-modal" class="md:w-2xl"> <div class="space-y-6"> <div> <flux:heading size="lg">Create New User</flux:heading> <flux:subheading>Add a new user to the system</flux:subheading> </div> {{-- This would contain your user creation form --}} <div class="text-center py-8 text-gray-500"> <flux:icon.user-plus class="w-12 h-12 mx-auto mb-4" /> <p>User creation form would go here</p> <p class="text-sm">Implement your user creation component</p> </div> <div class="flex justify-end space-x-2"> <flux:modal.close> <flux:button variant="ghost">Cancel</flux:button> </flux:modal.close> <flux:button>Create User</flux:button> </div> </div> </flux:modal> </div>
3. Register the Component
Add to your AppServiceProvider
or create a dedicated service provider:
use Livewire\Livewire; public function boot(): void { Livewire::component('custom-user-table', CustomUserTable::class); }
4. Use in Your Blade Templates
<livewire:custom-user-table />
Key Features Demonstrated
This comprehensive example showcases all available features:
- Complete Trait Integration: All major traits working together (HasEloquentTable, HasFilters, HasSorting, HasSearch, HasActions, HasToggleableColumns, HasDynamicPagination)
- Rich Column Types: Text, Component, DateTime, Boolean, JSON, and Action columns with various configurations
- Advanced Filtering: Multiple filter types including DeletedFilter, ValuePresentFilter, BooleanFilter, DateRangeFilter, and SelectFilter
- Interactive Actions: Both modal actions (edit, view details) and direct actions (ban, delete, restore) with conditional visibility
- Dynamic UI Controls: Column toggles, pagination size selection, search functionality, and filter management
- PostgreSQL Features: JSON column with path querying and type casting
- User Experience: Hover effects, sorting indicators, filter pills, and responsive modals
Benefits of This Approach
- Modularity: Pick and choose only the traits you need for simpler implementations
- Full Feature Set: This example shows how all features work together seamlessly
- Customization: Complete control over UI, behavior, and data presentation
- Performance: Optimized queries with relation handling, select optimization, and efficient pagination
- Flexibility: Easy to extend, modify, or simplify based on your specific requirements
- Reusability: Use this pattern across different models and use cases
- Maintainability: Clear separation of concerns with trait-based architecture
Customization Options
You can adapt this example by:
- Simplifying: Remove traits you don't need (e.g., remove HasActions for read-only tables)
- Extending: Add custom column types by extending the abstract Column class
- Custom Filters: Build specialized filters by extending the abstract Filter class
- Custom Operations: Create new operations for DirectAction beyond the provided ones
- UI Modifications: Customize the Blade template for your design system
- Model-Specific Features: Add model-specific logic in visibility conditions and transformations
- Integration: Connect with your existing authentication, authorization, and business logic
This modular approach allows you to start with this comprehensive example and adapt it to your exact needs, whether you want a full-featured admin interface or a simple data display table.
TODO
- Nothing for now
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see fork the project and adjust as much as u want to. But please dont expect me to answer to any PR or Issues.
Credits
License
The MIT License (MIT). Please see License File for more information.