Action Column

UX DataTables builds row actions from an Actions collection. The recommended entry point is AbstractDataTable::configureActions().

use App\Entity\User;
use Pentiminax\UX\DataTables\Attribute\AsDataTable;
use Pentiminax\UX\DataTables\Column\NumberColumn;
use Pentiminax\UX\DataTables\Column\TextColumn;
use Pentiminax\UX\DataTables\Model\AbstractDataTable;
use Pentiminax\UX\DataTables\Model\Action;
use Pentiminax\UX\DataTables\Model\Actions;

#[AsDataTable(User::class)]
final class UsersDataTable extends AbstractDataTable
{
    public function configureColumns(): iterable
    {
        yield NumberColumn::new('id', 'ID');
        yield TextColumn::new('email', 'Email');
        yield TextColumn::new('status', 'Status');
    }

    public function configureActions(Actions $actions): Actions
    {
        return $actions
            ->setColumnLabel('Actions')
            ->add(
                Action::edit('Edit')
                    ->setClassName('btn btn-sm btn-warning')
                    ->setIcon('bi bi-pencil')
            )
            ->add(
                Action::delete('Delete')
                    ->setClassName('btn btn-sm btn-danger')
                    ->setIcon('bi bi-trash')
                    ->askConfirmation('Delete this user?')
                    ->displayIf('status', 'draft')
            );
    }

    protected function mapRow(mixed $item): array
    {
        /** @var User $item */
        return [
            'id'     => $item->getId(),
            'email'  => $item->getEmail(),
            'status' => $item->getStatus(),
        ];
    }
}

When configureActions() returns at least one action, AbstractDataTable automatically appends an ActionColumn named actions.

Action API

Factory Methods

Method Description
``Action::delete($label = 'Delete', $className = 'btn btn-danger')``Create the built-in delete action
``Action::detail($label = 'Detail', $className = 'btn btn-primary')``Create a link action to a detail page
``Action::edit($label = 'Edit', $className = 'btn btn-warning')``Create an inline edit action (opens the configured edit modal)

Fluent Configuration

Method Description
`setLabel(string $label)`Override the button label
`setClassName(string $className)`Customize button classes
`setIcon(string $icon)`Render an icon before the label
`askConfirmation(string $message)`Display a browser confirmation prompt before the action
`displayIf(string $field, mixed $value)`Show the action only when `row[field] === value`
`setIdField(string $idField)`Use another row key instead of `id`
`setEntityClass(string $entityClass)`Set the Doctrine entity class explicitly
`linkToUrl(string|callable $url)`Set the URL for detail actions (static string or per-row callable)

When linkToUrl() receives a callable, the argument depends on how the row was produced:

  • AbstractDataTable + provider or setData($objects): the callable receives the original source object
  • manual DataTable::data([...]) inline rows: the callable receives the row array

Actions API

Method Description
`add(Action $action)`Register an action for the column
`remove(ActionType $type)`Remove a previously registered action
`setColumnLabel(string $label)`Customize the action column header

Actions stores one action per ActionType. The public enum values are:

use Pentiminax\UX\DataTables\Enum\ActionType;

ActionType::Delete; // value: DELETE
ActionType::Detail; // value: DETAIL
ActionType::Edit;   // value: EDIT

Manual Usage with DataTableBuilderInterface

If you build tables manually, create an Actions collection and wrap it with ActionColumn::fromActions():

use App\Entity\User;
use Pentiminax\UX\DataTables\Column\ActionColumn;
use Pentiminax\UX\DataTables\Column\TextColumn;
use Pentiminax\UX\DataTables\Model\Action;
use Pentiminax\UX\DataTables\Model\Actions;

$actions = (new Actions())
    ->setColumnLabel('Operations')
    ->add(
        Action::delete()
            ->setEntityClass(User::class)
            ->setIdField('uuid')
            ->askConfirmation('Delete this user?')
    );

$table = $builder
    ->createDataTable('users')
    ->columns([
        TextColumn::new('email', 'Email'),
        ActionColumn::fromActions('actions', 'Operations', $actions),
    ])
    ->data([
        ['uuid' => '8f9f0c31', 'email' => 'john@example.com'],
    ]);

Manual tables must provide the entity class themselves because there is no #[AsDataTable] attribute to infer it from.

Inline Edit (Modal)

Action::edit() opens a configured edit modal with an auto-generated Symfony Form. See the dedicated Edit Modal page for full documentation: template overrides, column-to-form mapping, primary key handling, and examples.

Ajax Endpoints

All action endpoints are handled by built-in Stimulus controllers. Import the bundle routes:

// config/routes/ux_datatables.php
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;

return static function (RoutingConfigurator $routes): void {
    $routes->import('@DataTablesBundle/config/routes.php');
};

Delete Endpoint

DELETE /datatables/ajax/delete — payload: entity, id, topics (optional Mercure topics).

Edit Form Endpoints

  • GET /datatables/ajax/edit-form — returns the rendered modal HTML
  • POST /datatables/ajax/edit-form — validates and persists the form data

These endpoints are only available when symfony/form is installed.