Type to search columns, filters, options, and extensions.

↑↓ to navigate · Enter to open · Esc to close

Documentation

Choice Column

Map finite value sets (enums, statuses) to human-readable labels with optional badge rendering

The ChoiceColumn maps a field’s raw value to a human-readable label. It optionally renders the label as a colored badge with a per-value semantic variant. PHP 8.1 BackedEnum classes are supported natively.

Badge markup is produced by a frontend column style adapter: Bootstrap 5 classes when a Bootstrap DataTables stylesheet is detected, Tailwind utilities otherwise (including the default dt theme).

Basic Usage

use Pentiminax\UX\DataTables\Column\ChoiceColumn;

ChoiceColumn::new('status', 'Status')
    ->setChoices([
        'active'   => 'Active',
        'inactive' => 'Inactive',
        'pending'  => 'Pending',
    ]);

Using a BackedEnum

Pass a BackedEnum class directly, or pass ::cases(). The mapping is auto-generated from case->value => case->name.

enum Status: string
{
    case Active   = 'active';
    case Inactive = 'inactive';
    case Pending  = 'pending';
}

ChoiceColumn::new('status', 'Status')
    ->setChoices(Status::cases());
// Generates: ['active' => 'Active', 'inactive' => 'Inactive', 'pending' => 'Pending']

Translating Labels

Cases of an enum that implements Symfony’s TranslatableInterface are translated when the table renders, in the locale of the current request. The ChoiceFilter does the same, so the column and its filter stay in sync:

use Symfony\Contracts\Translation\TranslatableInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

enum Status: string implements TranslatableInterface
{
    case Active   = 'active';
    case Inactive = 'inactive';

    public function trans(TranslatorInterface $translator, ?string $locale = null): string
    {
        return $translator->trans('status.'.$this->value, [], null, $locale);
    }
}

ChoiceColumn::new('status', 'Status')
    ->setChoices(Status::class);

Rendering as Badges

Use renderAsBadges() to wrap each label in a badge. Map individual values to semantic color variants (success, danger, warning, info, primary, secondary, light, dark), and provide a fallback for unmapped values.

ChoiceColumn::new('status', 'Status')
    ->setChoices(Status::cases())
    ->renderAsBadges(
        badgeSelector: [
            'active'   => 'success',
            'inactive' => 'danger',
            'pending'  => 'warning',
        ],
        defaultVariant: 'secondary',
    );

The same PHP configuration works with Bootstrap 5 and Tailwind — only the generated HTML classes change based on the detected DataTables CSS framework.

Default Badge Variant

When renderAsBadges() is called without a badgeSelector map (or for values not present in the map), the defaultVariant is used. It defaults to 'secondary'.

ChoiceColumn::new('category', 'Category')
    ->setChoices(['foo' => 'Foo', 'bar' => 'Bar'])
    ->renderAsBadges(); // all values use 'secondary' variant

API Reference

MethodDescription
ChoiceColumn::new(string $name, string $title = '')Creates a new ChoiceColumn (type: html)
setChoices(array|string $choices)Accepts a value => label array, a BackedEnum class-string, or a BackedEnum::cases() list
renderAsBadges(array|bool $badgeSelector = [], string $defaultVariant = 'secondary')Enables badge rendering with per-value semantic color variants

Complete Example

use Pentiminax\UX\DataTables\Attribute\AsDataTable;
use Pentiminax\UX\DataTables\Column\ChoiceColumn;
use Pentiminax\UX\DataTables\Column\NumberColumn;
use Pentiminax\UX\DataTables\Column\TextColumn;
use Pentiminax\UX\DataTables\Model\AbstractDataTable;

enum OrderStatus: string
{
    case Draft     = 'draft';
    case Confirmed = 'confirmed';
    case Shipped   = 'shipped';
    case Cancelled = 'cancelled';
}

#[AsDataTable(Order::class)]
final class OrdersDataTable extends AbstractDataTable
{
    public function configureColumns(): iterable
    {
        yield NumberColumn::new('id', 'ID');
        yield TextColumn::new('reference', 'Reference');
        yield ChoiceColumn::new('status', 'Status')
            ->setChoices(OrderStatus::class)
            ->renderAsBadges([
                'draft'     => 'secondary',
                'confirmed' => 'primary',
                'shipped'   => 'success',
                'cancelled' => 'danger',
            ]);
    }

    protected function mapRow(mixed $row): array
    {
        return [
            'id'        => $row->getId(),
            'reference' => $row->getReference(),
            'status'    => $row->getStatus()->value,
        ];
    }
}