Installation:
composer require araise/table-bundle
yarn add tailwindcss postcss-loader sass-loader sass autoprefixer --dev
Configure tailwind.config.js and webpack.config.js as per the docs.
Basic Setup:
default_locale in config/packages/framework.yaml is set to de for German translations (optional).{% block stylesheets %}
{{ parent() }}
@import "~@araise/table-bundle/styles/_tailwind.scss";
{% endblock %}
First Table: Create a controller with a Doctrine-backed table:
#[Route('/', name: 'index')]
public function index(TableFactory $tableFactory, PostRepository $postRepository): Response
{
$table = $tableFactory->create('posts', null, [
'dataloader_options' => [
DoctrineDataLoader::OPT_QUERY_BUILDER => $postRepository->createQueryBuilder('post'),
],
]);
$table
->addColumn('title')
->addColumn('description')
->addAction('detail', [
'route' => 'detail',
'route_parameters' => fn($post) => ['id' => $post->getId()],
]);
return $this->render('index.html.twig', ['table' => $table]);
}
Render in Twig:
{{ araise_table_render(table) }}
Data Loading:
DoctrineDataLoader for database-backed tables (default).
$tableFactory->create('posts', null, [
'dataloader_options' => [
DoctrineDataLoader::OPT_QUERY_BUILDER => $repo->createQueryBuilder('p'),
],
]);
ArrayDataLoader for static data:
$tableFactory->create('projects', ArrayDataLoader::class, [
'dataloader_options' => [ArrayDataLoader::OPT_DATA => $arrayData],
]);
Column Configuration:
$table->addColumn('title'); // Auto-detects accessor
$table->addColumn('description', 'Beschreibung'); // Custom label
$table->addColumn('Name', null, ['accessor_path' => '[name]']);
$table->addColumn('email', 'E-Mail', ['formatter' => 'email']);
Actions:
$table->addAction('edit', [
'label' => 'Bearbeiten',
'route' => 'edit_post',
'route_parameters' => fn($post) => ['id' => $post->getId()],
]);
$table->addAction('delete', [
'label' => 'Löschen',
'js' => 'confirmDelete(this)',
]);
Filters:
FilterExtension:
$table->getFilterExtension()
->addFilterType('status', 'Status', ChoiceFilterType::class, [
ChoiceFilterType::OPT_CHOICES => ['draft', 'published'],
]);
$table->getFilterExtension()
->predefineFilter('featured', 'published', TextFilterType::CRITERIA_EQUAL, 'published')
->and('author', TextFilterType::CRITERIA_CONTAINS, 'John');
Pagination:
$tableFactory->create('posts', null, [
'pagination' => [
'page_size' => 20,
'page_parameter' => 'page',
],
]);
araise_table_render (full) or araise_table_only_render (no pagination/filters).araise_table.enable_turbo: true) for SPA-like behavior.core.formatter tag:
services:
App\Formatter\CustomFormatter:
tags: ['core.formatter']
app.scss:
@layer components {
.araise-table {
&__cell { @apply py-2; }
}
}
Tailwind Configuration:
primary and error colors in tailwind.config.js will break the bundle’s styles../vendor/araise/**/*.{html,html.twig,js} is included in content in tailwind.config.js.@tailwind directives in app.scss.DataLoader Quirks:
OPT_JOINS in filter configurations:
$table->getFilterExtension()->addFilterType('city', 'City', ChoiceFilterType::class, [
FilterType::OPT_JOINS => ['c' => 'p.address.city'],
]);
[key]) for nested arrays.Filter Issues:
CRITERIA_EQUAL are case-sensitive unless configured otherwise.OPT_JSON_SEARCH_URL routes are properly defined and accessible.Performance:
DoctrineDataLoader to avoid memory issues:
$qb->setFirstResult(($page - 1) * $pageSize)->setMaxResults($pageSize);
OPT_JOINS to fetch related data upfront and avoid N+1 queries.Translation:
Table Dump:
Use dump($table->getConfiguration()) to inspect the table’s internal state (columns, filters, etc.).
Query Debugging:
Enable Doctrine’s query logging in config/packages/dev/doctrine.yaml:
doctrine:
dbal:
logging: true
profiling: true
Filter Debugging:
FilterExtension for applied filters:
dump($table->getFilterExtension()->getAppliedFilters());
OPT_COLUMN paths match your entity structure.Turbo Conflicts:
araise_table:
enable_turbo: false
Custom Filter Types:
Extend araise\TableBundle\Filter\Type\AbstractFilterType and register as a service:
class CustomFilterType extends AbstractFilterType {
public function apply(QueryBuilder $qb, $value, string $alias, string $column): void {
// Custom logic
}
}
Tag the service:
services:
App\Filter\CustomFilterType:
tags: ['araise.table.filter_type']
Custom DataLoaders:
Implement araise\TableBundle\DataLoader\DataLoaderInterface for non-Doctrine/array sources (e.g., API calls).
Twig Overrides:
Override templates by copying from vendor/araise/table-bundle/resources/views/ to templates/bundles/araise/table/.
Formatter Extensions: Create custom formatters for complex data (e.g., dates, enums):
class DateFormatter extends AbstractFormatter {
public static function getString($value): string {
return (new \DateTime($value))->format('d.m.Y');
}
}
Register and use:
$table->addColumn('created_at', null, ['formatter' => 'date']);
How can I help you explore Laravel packages today?