Back to Course |
Filament 3 From Scratch: Practical Course

Column Formatting: Badges, URLs, Labels, Alignment, Dates

Filament Table Builder has dozens of ways how to customize column values. In this lesson, I will touch on the most commonly used ones.


Show as Tags/Badges

Filament has a general concept of a "Badge", I personally call it a "Tag", which is just a visual representation of a text/number surrounded by a border.

Let's take a look at it by just adding ->badge() to two columns in our Products table: status and tags.

return $table
->columns([
Tables\Columns\TextColumn::make('name'),
Tables\Columns\TextColumn::make('price'),
Tables\Columns\TextColumn::make('status')
->badge(),
Tables\Columns\TextColumn::make('category.name'),
Tables\Columns\TextColumn::make('tags.name')
->badge(),
])

Here's the visual result:

As you can see, Filament automatically wraps the text as a "badge". Not only does it work for a simple TextColumn, but also, in the case of the belongsToMany relationship, it shows multiple badges instead of a comma-separated text.

You can also specify different colors for different badge values.

Tables\Columns\TextColumn::make('status')
->badge()
->color(fn (string $state): string => match ($state) {
'in stock' => 'primary',
'sold out' => 'danger',
'coming soon' => 'info',
}),

Here's how it looks now:

You can choose the colors from these options:

  • danger
  • gray
  • info
  • primary
  • success
  • warning

Clickable URL Column

You would often want some text to act as a link to another section or page. For example, the Product "Category" column could link to the Edit Category page or to a page of Products filtered by that Category.

For that, you can add the ->url() method to your column.

Tables\Columns\TextColumn::make('category.name')
->url(fn (Product $product): string => CategoryResource::getUrl('edit', ['record' => $product->category_id])),

Notice: to be honest, I prefer the short PHP functions syntax only if the line of code is actually short. In this case, for readability, I would choose this:

Tables\Columns\TextColumn::make('category.name')
->url(function (Product $product): string {
return CategoryResource::getUrl('edit', [
'record' => $product->category_id
]);
}),

And then, clicking on the category name would lead to the page something like /admin/categories/1/edit or similar. In our project, we don't have the page for Category Edit, as we generated that resource as --simple, so this was just an illustrative example.

As you can see, you can get the URL to any of the Filament Resources pages with the method getUrl():

  • CategoryResource::getUrl();: returns /admin/categories
  • CategoryResource::getUrl('create');: returns /admin/categories/create
  • CategoryResource::getUrl('edit', ['record' => 1]);: returns /admin/categories/1/edit

Different Label on Top

By default, Filament is trying to "guess" the column name in the header of the table from the field name, just putting the Title Case:

  • TextColumn::make('name') -> "Name"
  • TextColumn::make('category.name') -> "Category"
  • TextColumn::make('tags.name') -> "Tags"

But you can easily override it just by adding ->label() to the chained methods.

Tables\Columns\TextColumn::make('category.name')
->label('Category name'),

Here's the visual result:


Column Alignment

Also, you can specify a different alignment than the default "left". Again, it's as easy as adding a method to the chain:

Tables\Columns\TextColumn::make('price')
->sortable()
->money('usd')
->getStateUsing(function (Product $record): float {
return $record->price / 100;
})
->alignEnd(),

Shorter methods for each possible alignment:

  • alignLeft()
  • alignCenter()
  • alignRight()
  • alignJustify()
  • alignStart()
  • alignEnd()

Or, you can use a longer syntax with one standard method and specific Enum constants for the alignments:

use Filament\Support\Enums\Alignment;
 
// ...
Tables\Columns\TextColumn::make('price')
->alignment(Alignment::End)

Date Fields Formatting

If you want to show a timestamp field like created_at, you may choose which part to show: full date and time, only date, or "x days ago".

Just pick one of the methods to attach to the chain with the optional format parameter:

Tables\Columns\TextColumn::make('created_at')
->dateTime(),

Tables\Columns\TextColumn::make('created_at')
->dateTime('m/d/Y H:i'),

Tables\Columns\TextColumn::make('created_at')
->date(),

// This will run "diffForHumans" under the hood
Tables\Columns\TextColumn::make('created_at')
->since(),


These are just a few typical customizations of the table columns. For more examples and methods, please refer to the official documentation.