hassanhelfi / tabavel
Low-code dynamic tables for Laravel. We build the base (filtering, sorting, pagination, search) — you design the rows.
Requires
- php: ^8.2
- illuminate/database: ^10.0 || ^11.0 || ^12.0
- illuminate/http: ^10.0 || ^11.0 || ^12.0
- illuminate/pagination: ^10.0 || ^11.0 || ^12.0
- illuminate/support: ^10.0 || ^11.0 || ^12.0
Requires (Dev)
- orchestra/testbench: ^8.0 || ^9.0 || ^10.0
README
We build the base — you design the table.
Tabavel gives you filtering, sorting, pagination, and search out of the box.
You decide how much control you want:
| Mode | You write | Best for |
|---|---|---|
| Default | Nothing | Quick tables, admin panels |
| Custom Rows | Only <tr> rows |
When you need images, badges, custom buttons |
| Full Custom | Entire table HTML | Complete design freedom |
Install
composer require hassanhelfi/tabavel
Publish config (optional):
php artisan vendor:publish --tag=tabavel-config
Controller (Same for All Modes)
use HassanHelfi\Tabavel\Services\TableBuilder; use Illuminate\Support\Facades\DB; public function index(Request $request) { $query = DB::table('products') ->select(['id', 'name', 'price', 'category', 'active', 'created_at']); $table = TableBuilder::make($query) ->columns([ 'name' => ['type' => 'text', 'operators' => ['=', 'like']], 'price' => ['type' => 'text', 'operators' => ['=', '>', '<']], 'category' => [ 'type' => 'select', 'options' => ['electronics' => 'Electronics', 'clothing' => 'Clothing'], ], 'created_at' => ['type' => 'date'], ]) ->searchable(['name', 'category']) ->sortable(['id', 'name', 'price', 'created_at']) ->apply($request); return view('products.index', ['table' => $table]); }
Pagination Methods
Choose your pagination strategy in the controller:
// Simple pagination (default, fastest) $table = TableBuilder::make($query)->simplePaginate()->apply($request); // Full pagination with page numbers $table = TableBuilder::make($query)->paginate()->apply($request); // Cursor pagination (best for large datasets) $table = TableBuilder::make($query)->cursorPaginate()->apply($request);
Mode 1: Default (Auto-Render)
Zero effort. The table renders all columns automatically.
<x-tabavel-table :table="$table" />
That's it. Filters, sorting, pagination — all included.
Mode 2: Custom Rows
You write only the <tr> rows. Headers, filters, pagination are still automatic.
Use this when you need images, badges, custom buttons, or special formatting.
<x-tabavel-table :table="$table" custom-rows show-actions> @foreach($table->get() as $product) <tr> <td>{{ $product->id }}</td> <td> <img src="/uploads/{{ $product->image }}" width="50" height="50"/> </td> <td style="width:100px;">{{ $product->name }}</td> <td>{{ number_format($product->price) }} $</td> <td>{{ $product->category }}</td> <td> @if($product->active) <span class="badge bg-success">Active</span> @else <span class="badge bg-danger">Inactive</span> @endif </td> <td> <a href="/products/{{ $product->id }}/edit" class="btn btn-sm btn-primary"> Edit </a> </td> </tr> @endforeach </x-tabavel-table>
Mode 3: Full Custom
Don't use our views at all. Build your own table from scratch:
<input type="text" name="search" value="{{ request('search') }}"> <table class="my-custom-table"> <thead> <tr> @foreach($table->getColumns() as $col) <th>{{ $col['label'] }}</th> @endforeach </tr> </thead> <tbody> @foreach($table->get() as $row) <tr> {{-- Design however you want --}} <td>{{ $row->name }}</td> <td>{{ $row->price }}</td> </tr> @endforeach </tbody> </table> {{ $table->get()->links() }}
Component Props
| Prop | Type | Default | Description |
|---|---|---|---|
table |
TableBuilder |
null |
The TableBuilder instance |
id |
string |
'tabavel-table' |
HTML id for the table element |
action |
string |
current URL | Form action URL for filters |
custom-rows |
bool |
false |
Enable custom row mode |
show-actions |
bool |
false |
Show the "Actions" column |
searchable |
bool |
auto-detected | Show global search input |
pagination-view |
string |
auto-detected | Custom pagination view |
Column Configuration
->columns([ // Text filter with operators 'name' => [ 'type' => 'text', 'label' => 'Product Name', 'operators' => ['=', '!=', 'like', 'like%'], ], // Select dropdown filter 'status' => [ 'type' => 'select', 'options' => ['active' => 'Active', 'inactive' => 'Inactive'], ], // Date range filter (from/to) 'created_at' => [ 'type' => 'date', ], // Custom filter logic 'is_verified' => [ 'custom_filter' => function ($query, $operator, $value) { $value === 'yes' ? $query->whereNotNull('email_verified_at') : $query->whereNull('email_verified_at'); }, ], ])
Works With Eloquent
$table = TableBuilder::make(User::query()->select([...])) ->columns([...]) ->apply($request);
Publish & Customize Views
php artisan vendor:publish --tag=tabavel-views
Then edit resources/views/vendor/tabavel/bootstrap-5/table.blade.php.
License
MIT