Quick Start
Create your first DataTable in 5 minutes
Let’s create a simple users table in under 5 minutes.
-
Create the Table Class
// src/DataTables/UsersDataTable.php namespace App\DataTables; use Pentiminax\UX\DataTables\Column\NumberColumn; use Pentiminax\UX\DataTables\Column\TextColumn; use Pentiminax\UX\DataTables\Model\AbstractDataTable; use Pentiminax\UX\DataTables\Model\DataTable; final class UsersDataTable extends AbstractDataTable { public function configureColumns(): iterable { yield NumberColumn::new('id', 'ID'); yield TextColumn::new('firstName', 'First Name'); yield TextColumn::new('lastName', 'Last Name'); yield TextColumn::new('email', 'Email'); } public function configureDataTable(DataTable $table): DataTable { return $table ->data([ ['id' => 1, 'firstName' => 'John', 'lastName' => 'Doe', 'email' => 'john@example.com'], ['id' => 2, 'firstName' => 'Jane', 'lastName' => 'Smith', 'email' => 'jane@example.com'], ['id' => 3, 'firstName' => 'Bob', 'lastName' => 'Wilson', 'email' => 'bob@example.com'], ]) ->pageLength(10) ->searching(true) ->ordering(handler: true, indicators: true); } }Table classes are autoconfigured services, so there is nothing to register manually.
-
Create the Controller
// src/Controller/UserController.php namespace App\Controller; use App\DataTables\UsersDataTable; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; class UserController extends AbstractController { #[Route('/users', name: 'app_users')] public function index(UsersDataTable $table): Response { return $this->render('user/index.html.twig', [ 'table' => $table, ]); } } -
Create the Twig Template
{# templates/user/index.html.twig #} {% extends 'base.html.twig' %} {% block title %}Users{% endblock %} {% block body %} <div class="container mt-4"> <h1>Users</h1> {{ render_datatable(table) }} {# Or with custom attributes #} {{ render_datatable(table, {'class': 'table table-striped'}) }} </div> {% endblock %} -
Visit the Page
Navigate to
/usersin your browser. You should see a fully functional DataTable with:- Pagination
- Search box
- Column sorting
- Page length selector
Adding More Features
Enable Extensions
use Pentiminax\UX\DataTables\Enum\ButtonType;
use Pentiminax\UX\DataTables\Model\Extensions\ButtonsExtension;
use Pentiminax\UX\DataTables\Model\Extensions\SelectExtension;
use Pentiminax\UX\DataTables\Enum\SelectStyle;
public function configureDataTable(DataTable $table): DataTable
{
return $table
->data([/* ... */])
->extensions([
new ButtonsExtension([
ButtonType::COPY,
ButtonType::CSV,
ButtonType::EXCEL,
]),
new SelectExtension(SelectStyle::SINGLE),
]);
}
Load Data via Ajax
public function configureDataTable(DataTable $table): DataTable
{
return $table
->ajax('/api/users')
->serverSide()
->processing();
}
Customize Column Behavior
use Pentiminax\UX\DataTables\Column\EmailColumn;
use Pentiminax\UX\DataTables\Column\TextColumn;
$nameColumn = TextColumn::new('name', 'Name')
->setClassName('fw-bold')
->setOrderable(true)
->setSearchable(true)
->setWidth('200px');
$emailColumn = EmailColumn::new('email', 'Email')
->setOrderable(true);
Doctrine-Backed Tables
Add the #[AsDataTable] attribute to let the bundle query your entity and map its rows:
// src/DataTables/UsersDataTable.php
namespace App\DataTables;
use App\Entity\User;
use Pentiminax\UX\DataTables\Attribute\AsDataTable;
use Pentiminax\UX\DataTables\Model\AbstractDataTable;
use Pentiminax\UX\DataTables\Column\TextColumn;
use Pentiminax\UX\DataTables\Column\NumberColumn;
#[AsDataTable(User::class)]
final class UsersDataTable extends AbstractDataTable
{
public function configureColumns(): iterable
{
yield NumberColumn::new('id', 'ID');
yield TextColumn::new('firstName', 'First Name');
yield TextColumn::new('lastName', 'Last Name');
yield TextColumn::new('email', 'Email');
}
protected function mapRow(mixed $row): array
{
/** @var User $row */
return [
'id' => $row->getId(),
'firstName' => $row->getFirstName(),
'lastName' => $row->getLastName(),
'email' => $row->getEmail(),
];
}
}
Then in your controller:
#[Route('/users', name: 'app_users')]
public function index(UsersDataTable $table, Request $request): Response
{
$table->handleRequest($request);
if ($table->isRequestHandled()) {
return $table->getResponse();
}
return $this->render('user/index.html.twig', [
'table' => $table,
]);
}