Installation
composer require domenik88/datagrid-bundle
Add to config/bundles.php:
return [
// ...
Domenik88\DataGridBundle\Domenik88DataGridBundle::class => ['all' => true],
];
First Grid Definition
Create a YAML config file (e.g., config/datagrids/users.yml):
users:
datasource:
type: orm
entity: App\Entity\User
columns:
- { name: id, label: 'ID' }
- { name: username, label: 'Username' }
- { name: email, label: 'Email' }
Render in Controller
use Domenik88\DataGridBundle\Grid\GridFactory;
public function indexAction(GridFactory $gridFactory)
{
$grid = $gridFactory->create('users');
return $this->render('users/index.html.twig', ['grid' => $grid]);
}
Twig Template
{{ grid.render() }}
username).username or email.limit and offset in the datasource.datasource:
type: orm
entity: App\Entity\User
repository_method: findAll # Optional custom repo method
datasource:
type: odm
document: App\Document\Product
datasource:
type: vector
data: %app.some_array_data%
Leverage automatic type detection for rich UI/UX:
columns:
- { name: price, label: 'Price', type: currency, locale: 'en_US' }
- { name: is_active, label: 'Active', type: boolean }
- { name: created_at, label: 'Created At', type: datetime }
filters:
category:
type: select
data_source: method
data_source_method: getCategories
data_source_entity: App\Entity\Category
filters:
price:
type: range
from: 0
to: 1000
Define bulk operations in YAML:
mass_actions:
delete:
type: delete
label: 'Delete Selected'
icon: trash
route: user_delete_mass
route_parameters:
ids: $ids
Add per-row buttons:
row_actions:
edit:
type: link
label: 'Edit'
route: user_edit
route_parameters:
id: $id
view:
type: link
label: 'View'
route: user_view
route_parameters:
id: $id
Trigger exports via Twig:
<a href="{{ path('user_export', { grid: 'users', format: 'csv' }) }}">Export CSV</a>
Configure exports in YAML:
exports:
csv:
enabled: true
label: 'CSV'
excel:
enabled: true
label: 'Excel'
Use Twig to pass dynamic configs:
{% set gridConfig = {
'datasource': {
'type': 'orm',
'entity': 'App\Entity\\' ~ userType
},
'columns': columns
} %}
{{ grid.render(gridConfig) }}
Case Sensitivity in YAML
mapping to alias:
columns:
- { name: user_id, label: 'User ID', mapping: id }
Locale Mismatches
locale is not set for datetime/currency, defaults to system locale.columns:
- { name: price, type: currency, locale: 'en_US' }
Mass Action Route Conflicts
route_parameters in mass actions match your route definitions.route_name instead of route for clarity:
mass_actions:
archive:
type: link
label: 'Archive'
route_name: user_archive
route_parameters: { ids: $ids }
Performance with Large Datasets
findAll() for tables >10K rows. Use createQueryBuilder() in custom repo methods.query_builder to datasource:
datasource:
type: orm
entity: App\Entity\Order
query_builder: App\Repository\OrderRepository::createAdminQueryBuilder
Twig Template Caching
php bin/console cache:clear
Dump Grid Config Add to controller to inspect:
dump($grid->getConfig());
Check Query Logs Enable Doctrine logging to verify queries:
// config/packages/dev/doctrine.yaml
doctrine:
dbal:
logging: true
profiling: true
Filter Debugging
Use filter_data in Twig to inspect submitted filters:
<pre>{{ dump(grid.getFilterData()) }}</pre>
Custom Filter Types
Extend Domenik88\DataGridBundle\Filter\FilterInterface:
class CustomFilter implements FilterInterface { ... }
Register in services:
services:
app.custom_filter:
class: App\Filter\CustomFilter
tags:
- { name: datagrid.filter_type, type: custom }
Override Twig Rendering
Extend the base template (@Domenik88DataGrid/grid.html.twig) in your theme.
Dynamic Column Types
Use type: callback for custom logic:
columns:
- { name: status, type: callback, callback: App\DataGrid\StatusType }
Implement Domenik88\DataGridBundle\Type\ColumnTypeInterface.
Event Listeners Hook into grid lifecycle:
use Domenik88\DataGridBundle\Event\GridEvents;
$dispatcher->addListener(GridEvents::PRE_BUILD, function ($event) {
$event->getGrid()->addColumn(...);
});
Reuse Grids Across Controllers
Define grids in YAML and inject via GridFactory:
$grid = $gridFactory->create('users', $customConfig);
Conditional Columns
Use visible to toggle columns:
columns:
- { name: admin_only, visible: false } # Hidden by default
Toggle via JS or Twig:
{{ grid.showColumn('admin_only') }}
Inline Editing
Combine with row_actions and AJAX for quick edits:
row_actions:
edit_inline:
type: ajax
label: 'Edit'
route: user_edit_inline
route_parameters: { id: $id }
Multi-Grid Forms Chain grids for hierarchical data:
{{ grid.render('orders') }}
{% for order in grid.getResults() %}
{{ grid.render('order_items', { order_id: order.id }) }}
{% endfor %}
How can I help you explore Laravel packages today?