UX DataTables is a Symfony bundle integrating the DataTables library in Symfony applications.
- PHP 8.3 or higher
- Symfony StimulusBundle (installed through Symfony UX)
- Composer
Install the library via Composer:
composer require pentiminax/ux-datatablesuse App\Entity\User;
use Pentiminax\UX\DataTables\Attribute\AsDataTable;
use Pentiminax\UX\DataTables\Column\BooleanColumn;
use Pentiminax\UX\DataTables\Column\DateColumn;
use Pentiminax\UX\DataTables\Column\MoneyColumn;
use Pentiminax\UX\DataTables\Column\NumberColumn;
use Pentiminax\UX\DataTables\Column\TextColumn;
use Pentiminax\UX\DataTables\Model\AbstractDataTable;
#[AsDataTable(User::class)]
final class UserDataTable extends AbstractDataTable
{
public function configureColumns(): iterable
{
return [
NumberColumn::new('id', 'ID'),
TextColumn::new('firstName', 'First name'),
TextColumn::new('email', 'Email'),
DateColumn::new('createdAt', 'Created at'),
];
}
}Column variants are configured fluently after new():
TextColumn::new('name')->utf8();
TextColumn::new('content')->html()->utf8();
NumberColumn::new('price')->formatted();
MoneyColumn::new('price')->currency('EUR')->storedAsCents();
BooleanColumn::new('active')->renderAsSwitch();
TextColumn::new('internalCode')->disableColumnControl();disableColumnControl() removes all ColumnControl controls for the column without disabling
DataTables search processing.
#[Route('/users', name: 'app_users')]
public function index(UserDataTable $table, Request $request): Response
{
$table->handleRequest($request);
if ($table->isRequestHandled()) {
return $table->getResponse();
}
return $this->render('user/index.html.twig', [
'table' => $table,
]);
}{{ render_datatable(table) }}Tip: run
php bin/console make:datatableto scaffold a DataTable class from any Doctrine entity.
The bundle auto-registers a set of Ajax routes under /datatables/ajax/* (ux_datatables_ajax_data,
ux_datatables_ajax_delete, ux_datatables_ajax_edit, ux_datatables_ajax_edit_form,
ux_datatables_ajax_edit_form_submit, ux_datatables_ajax_detail, ux_datatables_ajax_templates).
The table token embedded in the rendered HTML identifies which table is requested, not who is requesting it — it is not a user-authentication or per-user authorization mechanism. If a table is displayed behind a firewall but these routes are left unprotected, the underlying data (and the edit/delete actions) can be reached by anyone holding the token.
Protect the routes with an access_control rule that matches the pages rendering your tables:
# config/packages/security.yaml
security:
access_control:
# access_control is first-match-wins; place this before any broader rule.
- { path: ^/datatables/ajax, roles: ROLE_ADMIN }Delete actions and inline boolean toggles additionally require an active session for CSRF
protection. Without one, their controls are rendered disabled (mutationsEnabled: false in the
table payload).
See Securing Ajax Routes for details.