Asynchronicity
Symfony UX Turbo is a Symfony bundle integrating the Hotwire Turbo library in Symfony applications. It allows having the same user experience as with Single Page Apps but without having to write a single line of JavaScript!
This bundle provides integration that works out-of-the-box.
The magic part
Make sure your application uses the Symfony UX Turbo. You don't have to configure anything extra, your data tables automatically work asynchronously! The magic comes from the base template, which wraps the whole table in the <turbo-frame>
tag:
{# @KreyuDataTable/themes/base.html.twig #}
{% block kreyu_data_table %}
<turbo-frame id="kreyu_data_table_{{ name }}">
{# ... #}
</turbo-frame>
{% endblock %}
This ensures every data table is wrapped in its own frame, making them work asynchronously.
This integration also works on other built-in templates, because they all extend the base one. If you're making a data table theme from scratch, make sure the table is wrapped in the Turbo frame, as shown above.
For more information, see official documentation about the Turbo frames.
Server-side responses for Turbo Frames
When a request originates from a Turbo Frame, you can return only the HTML of the data table instead of rendering the entire page. This significantly improves performance on pages with lots of content.
This bundle provides a helper for that: the DataTableTurboResponseTrait
. It renders just the table's markup so Turbo can replace the content of the requesting frame.
How it works under the hood:
- The
HttpFoundationRequestHandler
reads the Turbo-Frame request header and stores it in theDataTable
instance. - The
DataTable::isRequestFromTurboFrame()
method returns true when the header matches the table frame id (kreyu_data_table_<name>
). - In that case, you can short-circuit the controller and return only the table HTML using the trait method.
Example controller usage:
use Kreyu\Bundle\DataTableBundle\DataTableFactoryAwareTrait;
use Kreyu\Bundle\DataTableBundle\DataTableTurboResponseTrait;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class ProductController extends AbstractController
{
use DataTableFactoryAwareTrait;
use DataTableTurboResponseTrait;
public function index(ProductRepository $productRepository, Request $request): Response
{
$query = $productRepository->createQueryBuilder('product');
$dataTable = $this->createDataTable(ProductDataTableType::class, $query);
$dataTable->handleRequest($request);
if ($dataTable->isRequestFromTurboFrame()) {
// Return only the table's HTML so Turbo can replace the requesting <turbo-frame>
return $this->createDataTableTurboResponse($dataTable);
}
// Initial (non-Turbo) request: render the full page
return $this->render('home/index.html.twig', [
'products' => $dataTable->createView(),
]);
}
}
Notes:
- Make sure your table is wrapped in a
<turbo-frame>
as shown above; built-in themes already do this. - Turbo sends the Turbo-Frame header with the frame id; the bundle reads it for you. You don't need to access headers directly.
- The trait requires Twig to be available in your controller service (it is auto-wired by Symfony via the
#[Required]
setter).
Prefetching
Since Turbo v8, hovering over the links for more than 100ms will prefetch their content. This is enabled by default, and this bundle is no exception. If you wish to disable prefetching for a specific link (e.g. pages with expensive rendering), you can set the data-turbo-prefetch
attribute to false
, for example:
$builder->addRowAction('show', ButtonActionType::class, [
'attr' => [
// note that this "false" should be string, not a boolean
'data-turbo-prefetch' => 'false',
],
]);
Alternatively you can disable it application wide using a meta tag:
<meta name="turbo-prefetch" content="false">
For more information, see official documentation about the prefetching links on hover.