pentiminax/ux-datatables

DataTables.net integration for Symfony

Maintainers

Package info

github.com/pentiminax/ux-datatables

Type:symfony-bundle

pkg:composer/pentiminax/ux-datatables

Transparency log

Statistics

Installs: 9 198

Dependents: 0

Suggesters: 0

Stars: 72

Open Issues: 12

v0.61.0 2026-06-30 12:53 UTC

This package is auto-updated.

Last update: 2026-07-17 00:46:27 UTC


README

Latest Stable Version PHP Version Downloads total Coverage

UX DataTables is a Symfony bundle integrating the DataTables library in Symfony applications.

Video tutorial

Requirements

  • PHP 8.3 or higher
  • Symfony StimulusBundle (installed through Symfony UX)
  • Composer

Installation

Install the library via Composer:

composer require pentiminax/ux-datatables

Usage

1. Declare a DataTable

use 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.

2. Wire it in a controller

#[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,
    ]);
}

3. Render in Twig

{{ render_datatable(table) }}

Tip: run php bin/console make:datatable to scaffold a DataTable class from any Doctrine entity.

Security

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.

Documentation