Installation:
composer require symfony/ux-twig-component
Ensure your project uses Symfony 6.3+ or Symfony 7.x (check requirements).
Enable the Bundle:
Add to config/bundles.php:
return [
// ...
Symfony\UX\TwigComponent\TwigComponentBundle::class => ['all' => true],
];
First Use Case: Render a basic alert component in a Twig template:
{{ include_ux_twig_component('alert', {
type: 'success',
title: 'Success!',
text: 'Your action was completed.'
}) }}
Verify the output matches the alert example.
Component Registration:
Extend existing components or create custom ones via TwigComponentExtension:
// src/Twig/AppExtension.php
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
#[AsTwigComponent('my_component')]
public function myComponent(array $data): string
{
return $this->renderView('components/my_component.html.twig', $data);
}
Template Integration:
Use include_ux_twig_component in Twig:
{# Pass dynamic data #}
{{ include_ux_twig_component('my_component', {
title: 'Dynamic Title',
items: ['Item 1', 'Item 2']
}) }}
Data Binding: Bind objects to components for cleaner templates:
// Controller
return $this->render('page.html.twig', [
'userAlert' => new UserAlert($user),
]);
{# Template #}
{{ include_ux_twig_component('alert', userAlert) }}
Component Inheritance:
Extend base components (e.g., alert) to add functionality:
#[AsTwigComponent('custom_alert')]
public function customAlert(array $data): string
{
$data['extra'] = 'Custom logic here';
return $this->renderView('components/custom_alert.html.twig', $data);
}
Reusable Blocks:
Use Twig’s {% block %} within components for modularity:
{# components/base_card.html.twig #}
<div class="card">
{% block content %}{% endblock %}
</div>
Event-Driven Components: Trigger events in components (e.g., for Turbo interactions):
{{ include_ux_twig_component('modal', {
onClose: 'turbo:click->#modal-close'
}) }}
Component Naming Conflicts:
Ensure custom component names (e.g., my_component) don’t clash with Symfony’s built-in components. Prefix with your bundle name (e.g., app_my_component).
Circular Dependencies:
Avoid circular references between components and their templates. Use renderView sparingly to prevent infinite loops.
Data Type Mismatches: Components expect specific data structures. Validate inputs:
#[AsTwigComponent('user_card')]
public function userCard(array $data): string
{
if (!isset($data['user'])) {
throw new \InvalidArgumentException('User data required.');
}
// ...
}
Check Registered Components: Dump available components in Twig:
{{ dump(_twig_ux_components) }}
Template Paths:
Ensure component templates (e.g., components/alert.html.twig) are in your Twig loader paths. Use debug:config twig to verify.
Event Listeners: Debug Turbo/Stimulus events by inspecting the browser’s Network tab for Mercure updates or Turbo streams.
Custom Attributes: Add attributes to components for metadata or validation:
#[AsTwigComponent('validated_form')]
#[Attribute\RequiresDataType('form')]
public function validatedForm(array $data): string { ... }
Dependency Injection:
Inject services into components via Twig’s Environment:
public function __construct(private Environment $twig)
{
$this->twig = $twig;
}
Testing:
Test components in isolation using TwigTester:
$twig = new \Twig\Environment($loader);
$twig->addExtension(new TwigComponentExtension());
$result = $twig->render('components/alert.html.twig', ['type' => 'error']);
$this->assertStringContainsString('Error', $result);
# config/packages/twig.yaml
twig:
cache: '%kernel.cache_dir%/twig'
How can I help you explore Laravel packages today?