Filament Table: Dynamic Column Based on other Columns with Accessor

If you need to show a Table column that is not directly from the DB table but calculated from other columns, the best way is to use the Laravel feature of Eloquent Accessor. Let me show you how.

For example, you have columns users.created_at and users.email_verified_at, standard in Laravel projects.

And you want to show the third column of time difference between them. In other words, how fast the user verified their email.


Filament State Methods Wouldn't Work

If you try to create this dynamic column with Filament options like ->formatStateUsing() or ->state() on the column, it wouldn't work:

app/Filament/Resources/UserResource.php:

public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name'),
Tables\Columns\TextColumn::make('created_at'),
Tables\Columns\TextColumn::make('email_verified_at'),
Tables\Columns\TextColumn::make('verified_in_time')
// Both of the options above would NOT work
->state(function (User $record) {
// return ...
})
->formatStateUsing(function (Model $record) {
// return ...
}),
])

This is because those "state" options rely on the same column to be modified. And since the column verified_in_time isn't returned from the Eloquent query, Filament would skip those methods and just show an empty value in the table.


The Solution: Eloquent Accessor

You need to define it as an Attribute in the Eloquent Model and calculate it there. Then, Filament would recognize it as a column without any additional modifier methods.

app/Models/User.php:

class User extends Authenticatable
{
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
 
}
 
public function getVerifiedInTimeAttribute()
{
return $this->email_verified_at?->diffForHumans($this->created_at);
}
}

And then you can use it as a "regular" column in the Filament table:

app/Filament/Resources/UserResource.php:

public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name'),
Tables\Columns\TextColumn::make('created_at'),
Tables\Columns\TextColumn::make('email_verified_at'),
Tables\Columns\TextColumn::make('verified_in_time'),
])

Remember that for this particular example with datetime columns, you must also perform casts() in the Eloquent Model for the email_verified_at to calculate the difference this way, with the Carbon library under the hood. By default, the column created_at is cast to datetime automatically by Laravel for every model.


If you want more Filament examples, you can find more real-life projects on our FilamentExamples.com.

avatar
Erdo “Music Live” Waka

hallo admin, can we make custom table ? for make complex table, if it can, can you make the tutorial,

avatar

Hi, we are unsure what you mean by "make complex table". Can you give an example?

Like our articles?

Become a Premium Member for $129/year or $29/month
What else you will get:
  • 59 courses (1057 lessons, total 42 h 44 min)
  • 78 long-form tutorials (one new every week)
  • access to project repositories
  • access to private Discord

Recent Premium Tutorials