Admin Panel
Building Tables
Filament includes a table builder which can be used to create interactive tables in the admin panel.
Tables have columns and filters, which are defined in two methods on the table object.
Here is an example table configuration for a CustomerResource
:
use Filament\Resources\Tables\Columns;use Filament\Resources\Tables\Filter;use Filament\Resources\Tables\Table; public static function table(Table $table){ return $table ->columns([ Columns\Text::make('name')->primary(), Columns\Text::make('email')->url(fn ($customer) => "mailto:{$customer->email}"), Columns\Text::make('type') ->options([ 'individual' => 'Individual', 'organization' => 'Organization', ]), Columns\Text::make('birthday')->date(), Columns\Boolean::make('is_active')->label('Active?'), ]) ->filters([ Filter::make('individuals', fn ($query) => $query->where('type', 'individual')), Filter::make('organizations', fn ($query) => $query->where('type', 'organization')), Filter::make('active', fn ($query) => $query->where('is_active', true)), ]);}
Columns
Resource column classes are located in the Filament\Resources\Tables\Columns
namespace.
All columns have access to the following customization methods:
Column::make($name) ->action($action) // Set Livewire action that should be called when this column is clicked. The current record key will be passed in as a parameter. ->getValueUsing($callback = fn ($record) => $record->getAttribute('{column name}')) // Set the callback used to retrieve the value of the column from a given record. ->label($label) // Set custom label text for with the column header, which is otherwise automatically generated based on its name. It supports localization strings. ->primary() // Sets the column as primary, which emphasises it and links to access a record. ->searchable() // Allows the values in this column to be searched. ->sortable() // Allows the values in this column to be sorted. ->url($url, $shouldOpenInNewTab = false); // Set URL callback that should be used to generate a URL to send the user to when this column is clicked.
Since sorting and searching are done by the database,
sortable()
andsearchable()
will not be fully functional when using a customgetValueUsing()
callback.
Displaying Relationship Data
You set up columns that display results from a related model using dot syntax in its name:
Column::make('customer.name');
This would check for a customer
relationship on the parent model and output the related customer's name.
Calling Actions
You may want something to happen when a cell is clicked. Usually, this is opening a URL, or running a custom Livewire action.
To open a URL when a cell is clicked, a callback is used to generate the destination. For example:
Column::make('website') ->url(fn ($record) => $record->website, true);
Cells of the above column will display the contents of the record's website
, and redirect the user to it when they click. The second parameter to url()
, true
, means that the website will open in a new tab when clicked.
Alternatively, you may specify a custom Livewire action that should run when the column is clicked. The primary key of the clicked record will be passed as a parameter to the action:
Column::make('username') ->action('editUsername');
Cells of the above column will call the editUsername()
Livewire action when clicked.
Boolean
The trueIcon()
and falseIcon()
methods support the name of any Blade icon component, and passes a set of formatting classes to it. By default, the Blade Heroicons package is installed, so you may use the name of any Heroicon out of the box. However, you may create your own custom icon components or install an alternative library if you wish.
Boolean::make($name) ->falseIcon($icon = 'heroicon-o-x-circle') // Set the icon that should be displayed when the cell is false. ->trueIcon($icon = 'heroicon-s-check-circle'); // Set the icon that should be displayed when the cell is true.
Icon
The options()
method supports the names of any Blade icon components, and passes a set of formatting classes to them. By default, the Blade Heroicons package is installed, so you may use the name of any Heroicon out of the box. However, you may create your own custom icon components or install an alternative library if you wish.
Icon::make($name) ->options($options = []); // Set the icon that should be displayed when the cell is a given value.
Here is an example usage of this column:
Icon::make('status') ->options([ 'heroicon-s-check-circle' => fn ($status) => $status === 'accepted', // When the `status` is `accepted`, render the `check-circle` Heroicon. 'heroicon-s-x-circle' => fn ($status) => $status === 'declined', // When the `status` is `declined`, render the `x-circle` Heroicon. 'heroicon-s-clock' => fn ($status) => $status === 'pending', // When the `status` is `pending`, render the `clock` Heroicon. ]);
Image
Image::make($name) ->disk($disk) // Set a custom disk that images should be read from. ->height($height = 40) // Set the height of the image in pixels. ->rounded() // Make the image preview fully rounded. ->size($size) // Set the height and width of the image in pixels. ->width($width); // Set the width of the image in pixels.
Text
Text::make($name) ->currency($symbol = '€', $decimalSeparator = '.', $thousandsSeparator = ',', $decimals = 2) // Format values in this column in a currency format. ->date($format = 'F j, Y') // Format values in this column as dates, using PHP date formatting tokens. ->dateTime($format = 'F j, Y H:i:s') // Format values in this column as date-times, using PHP date formatting tokens. ->default() // Set the default value for when this field does not exist. ->formatUsing($callback = fn ($value) => $value) // Set the callback used to format the value of the column. ->limit($limit) // Truncate the value of this column to a certain number of characters. ->options($options = []); // Set the key-value array of available values that this column could hold.
Other column types are coming soon. For more information, please see our Development Roadmap.
Developing Custom Column Types
To create a new column type, which may be used in any table, you may generate a class and cell view using:
php artisan make:filament-column Avatar --resource
Alternatively, simple custom columns may be created using a View
component, and passing the name of a cell $view
in your app:
Columns\View::make($view) ->data($data = []); // Set the key-value array of available data that the view has access to.
Filters
Filters are used to scope results in the table. Here is an example of a filter at allows only customers with a type
of individual
to be shown in the table:
Filter::make('individuals', fn ($query) => $query->where('type', 'individual'));
They have access to the following customization options:
Filter::make($name, $callback = fn ($query) => $query) ->label($label); // Set custom label text for with the filter, which is otherwise automatically generated based on its name. It supports localization strings.
You can define a default filter to be applied when no other filter is selected by the user by calling defaultFilter()
on the Table
object:
public static function table(Table $table){ return $table ->columns([ // ... ]) ->filters([ Filter::make('individuals', fn ($query) => $query->where('type', 'individual')), Filter::make('organizations', fn ($query) => $query->where('type', 'organization')), Filter::make('active', fn ($query) => $query->where('is_active', true)), ]) ->defaultFilter('individuals');}
Reusable Filters
You may wish to create a filter that you may reuse across multiple tables.
To create a reusable filter, you may use the following command:
php artisan make:filament-filter ActiveFilter --resource
This will create a new filter in the app/Filament/Resources/Tables/Filters
directory:
<?php namespace App\Filament\Resources\Tables\Filters; use Filament\Tables\Filter; class ActiveFilter extends Filter{ protected function setUp() { $this->name('active'); } public function apply($query) { return $query; }}
You may modify the filter's query in the apply()
method of that class:
public function apply($query){ return $query->where('is_active', true);}
Currently, filters are static and only one may be applied at a time. Parameter-based filters and support for applying multiple filters at once is coming soon. For more information, please see our Development Roadmap.
Context Customization
You may customize tables based on the page they are used. To do this, you can chain the only()
or except()
methods onto any column or filter.
use App\Filament\Resources\CustomerResource\Pages;use Filament\Resources\Tables\Filter;use Filament\Resources\Tables\Table; public static function table(Table $table){ return $table ->filters([ Filter::make('individuals', fn ($customer) => $customer->type === 'individual') ->only(Pages\ListCustomers::class), ]);}
In this example, the individuals
filter will only()
be available on the ListCustomers
page.
use App\Filament\Resources\CustomerResource\Pages;use Filament\Resources\Tables\Columns;use Filament\Resources\Tables\Table; public static function table(Table $table){ return $table ->columns([ Columns\Text::make('name') ->except(Pages\ListCustomers::class, fn ($column) => $column->primary()), ]);}
In this example, the name
column will be primary, except()
on the ListCustomers
page.
This is an incredibly powerful pattern, and allows you to completely customize a table contextually by chaining as many methods as you wish to the callback.
Edit on GitHubStill need help? Join our Discord community or open a GitHub discussion