Action Column
UX DataTables builds row actions from an Actions collection. The recommended entry point is AbstractDataTable::configureActions().
Recommended Usage with AbstractDataTable
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 orsetData($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 HTMLPOST /datatables/ajax/edit-form— validates and persists the form data
These endpoints are only available when symfony/form is installed.