Filament Tables allow you to implement tabs easily. But did you know you can specify the tab names/values dynamically from the database, also controlling the order in which they appear? Let's take a look.
In this example, we have the following database table schema and Models.
database/migrations/XXXXXX_create_tiers_table.php
Schema::create('tiers', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('order_column'); $table->timestamps();});
database/migrations/XXXXXX_create_customers_table.php
use App\Models\Tier; // ... Schema::create('customers', function (Blueprint $table) { $table->id(); $table->foreignIdFor(Tier::class)->nullable()->constrained(); $table->string('full_name'); $table->timestamps();});
app/Models/Tier.php
class Tier extends Model{ // ... protected $guarded = []; public function customers(): HasMany { return $this->hasMany(Customer::class); }}
app/Models/Customer.php
class Customer extends Model{ // ... protected $guarded = []; public function tier(): BelongsTo { return $this->belongsTo(Tier::class); }}
To add tabs, we must define the getTabs()
method to your List<Resource>.php
file. In this case, it is ListCustomers
.
app/Filament/Resources/CustomerResource/Pages/ListCustomers.php
namespace App\Filament\Resources\CustomerResource\Pages; use App\Filament\Resources\CustomerResource;use App\Models\Tier; use Filament\Actions;use Filament\Resources\Components\Tab; use Filament\Resources\Pages\ListRecords; class ListCustomers extends ListRecords{ protected static string $resource = CustomerResource::class; protected function getHeaderActions(): array { return [ Actions\CreateAction::make(), ]; } public function getTabs(): array { $tabs = ['all' => Tab::make('All')->badge($this->getModel()::count())]; $tiers = Tier::orderBy('order_column', 'asc') ->withCount('customers') ->get(); foreach ($tiers as $tier) { $name = $tier->name; $slug = str($name)->slug()->toString(); $tabs[$slug] = Tab::make($name) ->badge($tier->customers_count) ->modifyQueryUsing(function ($query) use ($tier) { return $query->where('tier_id', $tier->id); }); } return $tabs; }}
When returning the tabs array, the index of that array is a value of the activeTab
URL parameter. So, we can generate a slug from the Tier name instead of just having a number.
//... /admin/customers?activeTab=platinum$slug = str($name)->slug()->toString();
Tabs can have badges. The badge()
method also accepts closures to display data depending on your custom logic. In our case, we show the Customer count in that Tier.
->badge($tier->customers_count)
Eloquent Query is modified with the ->modifyQueryUsing()
method to filter records. Here, we extend the query to select Customers with the tier_id
of the activeTab
.
->modifyQueryUsing(function ($query) use ($tier) { return $query->where('tier_id', $tier->id);});
Tier tabs are sorted by the order_column
column in ascending order.
$tiers = Tier::orderBy('order_column', 'asc')
You can change the order of tabs by modifying the order_column
value on the EditTier
page.
Optionally, you can reorder rows directly on the ListTiers
page by adding these methods to the TierResource@table
method.
->defaultSort('order_column')->reorderable('order_column')
Implemented Tier and Customer Resources are as follows.
app/Filament/Resources/TierResource.php
use Filament\Forms\Components\TextInput; use Filament\Tables\Columns\TextColumn; class TierResource extends Resource{ // ... public static function form(Form $form): Form { return $form ->schema([ TextInput::make('name') ->required(), TextInput::make('order_column') ->required() ->numeric(), ]); } public static function table(Table $table): Table { return $table ->columns([ TextColumn::make('order_column'), TextColumn::make('name'), TextColumn::make('customers_count') ->counts('customers') ->badge(), ]) ->defaultSort('order_column') ->reorderable('order_column') // ... }}
app/Filament/Resources/CustomerResource.php
use App\Models\Tier; use Filament\Forms\Components\Select;use Filament\Forms\Components\TextInput;use Filament\Tables\Columns\TextColumn; class CustomerResource extends Resource{ // ... public static function form(Form $form): Form { return $form ->schema([ TextInput::make('full_name') ->required(), Select::make('tier_id') ->label('Tier') ->options(Tier::pluck('name', 'id')), ]); } public static function table(Table $table): Table { return $table ->columns([ TextColumn::make('full_name'), TextColumn::make('tier.name') ->badge(), ]) // ... }}
Congratulations! You've successfully implemented dynamic Tabs for your Filament Table.
If you want more Filament examples, you can find more real-life projects on our FilamentExamples.com.
No comments or questions yet...