A standalone, Tailwind+Livewire DataTable wrapper with Flux UI styling for Laravel.
Ready-to-use, highly customizable, and easy to extend for any Laravel project.
- ✅ Server-side pagination
- ✅ Column sorting with customizable direction
- ✅ Global search with debounce
- ✅ Per-page options for pagination
- ✅ Custom column rendering with callbacks
- ✅ Sortable/searchable column configuration
- ✅ Empty state handling
- ✅ Fully responsive & accessible
- ✅ Flux UI integration with beautiful, consistent styling
- ✅ Config-driven components with fallback options
- ✅ View mode switching between table and card views
- ✅ Filter modal with customizable filters
- ✅ Search input with live updates
- PHP ≥ 8.4
- Laravel ≥ 10.x
- Livewire ≥ 2.x
- TailwindCSS (via Laravel Mix or Vite)
- Flux UI (for default styling)
composer require ultraviolettes/flux-datatable
php artisan vendor:publish --provider="Ultraviolettes\FluxDataTable\FluxDataTableServiceProvider" --tag="config"
php artisan vendor:publish --provider="Ultraviolettes\FluxDataTable\FluxDataTableServiceProvider" --tag="views"
return [
// Default per-page options for pagination dropdown
'per_page' => [10, 25, 50, 100],
// Flux UI Table Configuration
'flux_ui' => [
// Enable/disable Flux UI pagination component
'use_pagination' => true,
// Enable/disable view mode table / card
'use_view_mode' => true,
],
];
This package now fully integrates with Flux UI Table components to provide a beautiful, consistent styling experience. The integration includes:
- Table Components: Uses Flux UI Table components for the main table structure
- Form Components: Uses Flux UI Input and Select components for search and pagination controls
- Utility Components: Uses Flux UI Empty State and Pagination components for better user experience
You can configure the Flux UI integration in the config/flux-datatable.php
file:
'flux_ui' => [
// Enable/disable Flux UI Table container component
'use_container' => true,
// Enable/disable Flux UI pagination component
'use_pagination' => true,
// Enable/disable Flux UI empty state component
'use_empty_state' => true,
],
If you disable any of these options, the package will fall back to standard HTML and Laravel's built-in components.
You can use the FluxDataTable facade to create a new data table:
use Ultraviolettes\FluxDataTable\Facades\FluxDataTable;
// In your controller
public function index()
{
$table = FluxDataTable::columns([
['label' => 'ID', 'field' => 'id'],
['label' => 'Name', 'field' => 'name'],
['label' => 'Email', 'field' => 'email'],
])->data(User::query());
return view('users.index', compact('table'));
}
Then in your blade view:
<div>
{!! $table !!}
</div>
You can configure columns with additional options:
FluxDataTable::columns([
[
'label' => 'ID',
'field' => 'id',
'sortable' => true,
'searchable' => true,
],
[
'label' => 'Name',
'field' => 'name',
'sortable' => true,
'searchable' => true,
],
[
'label' => 'Status',
'field' => 'status',
'sortable' => false,
'searchable' => false,
'render' => function($row) {
return '<span class="badge badge-' . $row->status . '">' . ucfirst($row->status) . '</span>';
}
],
[
'label' => 'Role',
'field' => 'role',
'sortable' => false,
'searchable' => false,
'render' => '<flux:badge size="lg" color="sky" variant="pill">
<div class="mr-2 h-2 w-2 rounded-full bg-blue-500"></div>
<span class="text-black">Admin</span>
</flux:badge>'
],
[
'label' => 'Actions',
'field' => null,
'sortable' => false,
'searchable' => false,
'render' => function($row) {
return '<a href="/users/' . $row->id . '/edit" class="btn btn-sm btn-primary">Edit</a>';
}
],
])->data(User::query());
You can customize the per-page options:
FluxDataTable::columns([
// your columns
])->data(User::query())
->perPageOptions([5, 15, 30, 50]);
If you prefer to use the Livewire component directly:
<livewire:flux-datatable::table
:columns="[
['label' => 'ID', 'field' => 'id'],
['label' => 'Name', 'field' => 'name'],
['label' => 'Email', 'field' => 'email'],
]"
:data="App\Models\User::query()"
:perPageOptions="[10, 25, 50, 100]"
/>
The FluxDataTable component now supports switching between table and card views:
// In your Livewire component or controller
$table = FluxDataTable::columns([
// your columns
])->data(User::query());
// Set the default view mode (optional, defaults to 'table')
$table->viewMode('card');
Users can switch between views using the built-in view mode buttons. The current view mode is preserved in the URL query string.
The FluxDataTable component includes a powerful filtering system that allows you to define filters for your data table. The filters are displayed in a modal that can be opened by clicking the "Filtres" button.
To define filters, override the filters()
method in your Livewire component:
use Ultraviolettes\FluxDataTable\Filters\SelectFilter;
use Ultraviolettes\FluxDataTable\Filters\DateFilter;
class UsersTable extends \Ultraviolettes\FluxDataTable\Http\Livewire\FluxDataTable
{
// ... other methods
public function filters(): array
{
return [
'status' => SelectFilter::make(__('Status'), 'status')
->options([
'' => 'Tous',
'active' => 'Actif',
'inactive' => 'Inactif',
'pending' => 'En attente',
]),
'role' => SelectFilter::make('Rôle', 'role')
->options([
'' => 'Tous',
'admin' => 'Administrateur',
'user' => 'Utilisateur',
'guest' => 'Invité',
]),
'created_at' => DateFilter::make(__('Creation date'), 'created_at')
->query(fn ($query, $date) => $query->whereDate('created_at', $date)),
];
}
}
The filter values are automatically applied to the query when the user selects a value from the filter dropdown. The filter values are also persisted in the URL query string, so users can share filtered views.
You can reset all filters to their default values by clicking the "Réinitialiser" button in the filter modal.
Currently, the following filter types are available:
- SelectFilter: A dropdown filter that allows users to select a single value from a list of options.
- DateFilter: A date picker filter that allows users to select a date for filtering.
More filter types will be added in future releases.
The search functionality is now enhanced with a dedicated search input:
// The search input is included by default in the table template
// The search property is automatically bound to the input
By default, the search functionality only searches in the 'name' field. You can customize which fields are searched by using the setSearchableFields
method or by passing the fields in the constructor:
// Using the setSearchableFields method
class UsersTable extends \Ultraviolettes\FluxDataTable\Livewire\FluxDataTable
{
public function mount()
{
parent::mount();
$this->setSearchableFields(['name', 'email', 'description']);
}
}
// Or when initializing the component
<livewire:users-table
:searchableFields="['name', 'email', 'description']"
/>
The search will now look for matches in all specified fields, using OR conditions between them.
You can also customize the search behavior in your Livewire component:
// In your Livewire component
public function updatingSearch()
{
// Custom logic when search is updated
$this->resetPage();
}
composer require --dev orchestra/testbench livewire/livewire
php artisan test
Example feature test in tests/Feature/FluxDataTableTest.php:
<?php
namespace Ultraviolettes\FluxDataTable\Tests\Feature;
use Livewire\Livewire;
use Orchestra\Testbench\TestCase;
use Ultraviolettes\FluxDataTable\FluxDataTableServiceProvider;
class FluxDataTableTest extends TestCase
{
protected function getPackageProviders($app)
{
return [
FluxDataTableServiceProvider::class,
\Livewire\LivewireServiceProvider::class,
];
}
/** @test */
public function it_displays_records()
{
$users = \App\Models\User::factory()->count(3)->create();
Livewire::test('flux-datatable::table', [
'columns' => [['label' => 'Name', 'field' => 'name']],
'data' => \App\Models\User::query(),
])->assertSee($users->first()->name);
}
}
- Fork the repo
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -am 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
Please follow the PSR-12 coding standard and run composer run format
before submitting.
This package is open-sourced under the MIT license.
See CHANGELOG.md for release notes and version history.