Filament: Badge Columns with Enums

If you have a set of options for radio/dropdowns in the Form, you may want to create a PHP Enum class. It will give you the benefit of re-using the same class and also automatically show colors/icons as a badge.

Before:

ProductResource.php:

public static function form(Form $form): Form
{
return $form
->schema([
// ... other fields
Forms\Components\Radio::make('status')
->options([
'in stock' => 'in stock',
'sold out' => 'sold out',
'coming soon' => 'coming soon',
]),
]);
}

After:

app/Enums/ProductStatus.php:

namespace App\Enums;
 
use Filament\Support\Contracts\HasIcon;
use Filament\Support\Contracts\HasLabel;
use Filament\Support\Contracts\HasColor;
 
enum ProductStatus: string implements HasLabel, HasColor, HasIcon
{
case IN_STOCK = 'in stock';
case SOLD_OUT = 'sold out';
case COMING_SOON = 'coming soon';
 
public function getLabel(): ?string
{
return match ($this) {
self::IN_STOCK => 'In stock',
self::SOLD_OUT => 'Sold out',
self::COMING_SOON => 'Coming soon',
};
}
 
public function getColor(): string|array|null
{
return match ($this) {
self::IN_STOCK => 'success',
self::SOLD_OUT => 'warning',
self::COMING_SOON => 'gray',
};
}
 
public function getIcon(): ?string
{
return match ($this) {
self::IN_STOCK => 'heroicon-m-pencil',
self::SOLD_OUT => 'heroicon-m-eye',
self::COMING_SOON => 'heroicon-m-check',
};
}
}

app/Models/Product.php

use App\Enums\ProductStatus;
 
class Product extends Model {
// ...
 
protected $casts = [
'status' => ProductStatus::class,
];
}

ProductResource.php:

use App\Enums\ProductStatus;
 
public static function form(Form $form): Form
{
return $form
->schema([
// ... other fields
Forms\Components\Radio::make('status')
->options(ProductStatus::class),
]);
}

It feels like a lot of work, right? But look at those methods getLabel(), getColor() and getIcon(). Now, in the Table of the Resource, you can just use the badge() method, and Enum will auto-style it for you.

public static function table(Table $table): Table
{
return $table
->columns([
// ... other columns
Tables\Columns\TextColumn::make('status')
->badge(),
]);
}

Like our articles?

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

Recent Premium Tutorials