Since our Customer table can have thousands of entries - we need a way to filter them by something. In our case, we will create tabs to group them by their Pipeline Stage like this:
In this lesson, we will do the following:
- Dynamically create tabs for each Pipeline Stage
- Create a new tab called
All
to show all Customers - Add counters to each tab to show how many Customers are in each group
Let's get started!
Creating the Tabs
To make tabs, we will modify our List file:
app/Filament/Resources/CustomerResource/Pages/ListCustomers.php
use App\Models\Customer;use App\Models\PipelineStage;use Filament\Resources\Components\Tab; // ... class ListCustomers extends ListRecords{ // ... public function getTabs(): array { $tabs = []; $tabs['all'] = Tab::make('All Customers') ->badge(Customer::count()); $pipelineStages = PipelineStage::orderBy('position')->withCount('customers')->get(); foreach ($pipelineStages as $pipelineStage) { $tabs[str($pipelineStage->name)->slug()->toString()] = Tab::make($pipelineStage->name) ->badge($pipelineStage->customers_count) ->modifyQueryUsing(function ($query) use ($pipelineStage) { return $query->where('pipeline_stage_id', $pipelineStage->id); }); } return $tabs; }}
Once this code is done, we should see tabs appearing above our table:
But what did we do here? Let's look at the code again with some comments:
public function getTabs(): array{ $tabs = []; // Adding `all` as our first tab $tabs['all'] = Tab::make('All Customers') // We will add a badge to show how many customers are in this tab ->badge(Customer::count()); // Load all Pipeline Stages $pipelineStages = PipelineStage::orderBy('position')->withCount('customers')->get(); // Loop through each Pipeline Stage foreach ($pipelineStages as $pipelineStage) { // Add a tab for each Pipeline Stage // Array index is going to be used in the URL as a slug, so we transform the name into a slug $tabs[str($pipelineStage->name)->slug()->toString()] = Tab::make($pipelineStage->name) // We will add a badge to show how many customers are in this tab ->badge($pipelineStage->customers_count) // We will modify the query to only show customers in this Pipeline Stage ->modifyQueryUsing(function ($query) use ($pipelineStage) { return $query->where('pipeline_stage_id', $pipelineStage->id); }); } return $tabs;}
That's it! This is all we had to do for the tabs to work.
In the next lesson, we will add an ability to view archived Customers and restore them.
Thank you for the very useful tutorials. I have a question. How to control the visibility of a table column depending on the active tab?
I found a solution ->visible(fn ($livewire) => $livewire->activeTab !== 'all')
Get only the pipelines that have clients:
I found this redundant :
Why?
This applies the
pipeline_stage_id
filter on the selected tab :) Without it - it wouldn't filter the records once you click, no?I think I've not understood what it does then because
is returning the correct customer count for each pipeline stage anyway.
So there's a few functions that this does. Especially if we are talking about tags:
->badge()
just displays the amount of people with that status->modifyQueryUsing()
allows you to click on the tab and filter records based on the filterThat way, you don't just get plain information, but also an additional filter on the table
Oh I see - this was new to me - thanks for the clarification.