Files
archived-ux-twig-component/CHANGELOG.md
Hugo Alliaume e2e686be45 [TwigComponent] Add support for AttributeValueInterface from twig/html-extra:^3.24.0 in ComponentAttributes
Close https://github.com/twigphp/Twig/issues/4790, replace https://github.com/twigphp/Twig/pull/4791.

This PR update `ComponentAttributes` to support `AttributeValueInterface` from Twig 3.24 with `html_attr_type` and HTML attributes merging strategy.

This helps resolve situations where merging HTML attributes needs to be more sophisticated than a simple `array_merge`.

For example in UX Toolkit, we have an issue where it's not possible to use a single `<twig:Button>` with `Dialog` and `Tooltip` triggers, both triggers define a `trigger_attrs` with some attributes that may conflict. Here a simplified version:
```
{%- set dialog_trigger_attrs = {
    'data-action': 'click->dialog#open',
} -%}
{%- set tooltip_trigger_attrs = {
    'data-action': 'mouseenter->tooltip#show mouseleave->tooltip#hide focus->tooltip#show blur->tooltip#hide',
} -%}

<twig:Button
    {{ ...dialog_trigger_attrs }}
    {{ ...tooltip_trigger_attrs }}
/>
```

Here, only `data-action="mouseenter->tooltip#show mouseleave->tooltip#hide focus->tooltip#show blur->tooltip#hide"` will be rendered, the value from `dialog_trigger_attrs` is purely ignored.

By supporting the HTML attributes merging strategy introduced in Twig HTML Extra 3.24, we can use the new Twig filter `html_attr_type`:
```twig
{%- set dialog_trigger_attrs = {
    'data-action': 'click->dialog#open'|html_attr_type('sst'),
} -%}
{%- set tooltip_trigger_attrs = {
    'data-action': 'mouseenter->tooltip#show mouseleave->tooltip#hide focus->tooltip#show blur->tooltip#hide'|html_attr_type('sst'),
} -%}
```

Combined to `html_attr_merge` (that return an array where some values are an instance of `Twig\Extra\Html\HtmlAttr\AttributeValueInterface`), the following example will correctly render `data-action="click->dialog#open mouseenter->tooltip#show mouseleave->tooltip#hide focus->tooltip#show blur->tooltip#hide"`:
```twig
<twig:Button
    {{ ...{}|html_attr_merge(dialog_trigger_attrs, tooltip_trigger_attrs) }}
/>
```
2026-03-23 13:55:11 +01:00

6.9 KiB

CHANGELOG

2.35

Add support for AttributeValueInterface from twig/html-extra:^3.24.0 in ComponentAttributes

2.33

  • Extended support for the index.html.twig template fallback when resolving namespaced anonymous components
  • Add support for dynamic template resolution with AsTwigComponent(template: FromMethod('getCustomFuntion'))

2.32

  • Add option profiler.collect_components to control component data collection in the profiler (enabled in debug mode by default)
  • Add support for using directory name as component name for anonymous components

2.30

  • Ensure compatibility with PHP 8.5

2.29.0

  • Add Symfony 8 support

2.25.2

  • Fix ComponentAttributes rendering when using StimulusAttributes as default attributes

2.25.1

  • [SECURITY] ComponentAttributes now requires a Twig\Runtime\EscaperRuntime instance as second argument
  • Remove HtmlAttributeEscaperInterface, TwigHtmlAttributeEscaper and ComponentAttributesFactory

2.25.0

  • [SECURITY] Make ComponentAttributes responsible for attribute escaping ensuring consistent and secure HTML output across all rendering contexts
  • Deprecate not passing an HtmlAttributeEscaperInterface to the ComponentAttributes constructor

2.20.0

2.17.0

  • Add nested attribute support #1405

2.16.0

  • Introduce CVA to style TwigComponent #1416
  • Drop Twig 2 support #1436
  • Fix full context is stored in profiler #1552
  • Add CVA (Class variant authority) integration #1416

2.15.0

  • Add the ability to render specific attributes from the attributes variable #1442
  • Restrict Twig 3.9 for now #1486
  • Build reproducible TemplateMap to fix possible post-deploy breakage #1497

2.14.0

  • Make ComponentAttributes traversable/countable
  • Fixed lexing some {# twig comments #} with HTML Twig syntax
  • Fix various usages of deprecated Twig code

2.13.0

  • [BC BREAK] Add component metadata to PreMountEvent and PostMountEvent
  • Added configuration to separate your components into different "namespaces"
  • Add outerScope variable reach variables from the parent template of an "embedded" component.
  • Deprecate calling ComponentTemplateFinder constructor without directory argument.
  • Add profiler integration: TwigComponentDataCollector and debug toolbar templates
  • Add search feature in debug:twig-component command.
  • Fix inconsistencies with how {% component %}/<twig:component> syntaxes are rendered vs component(): PostRenderEvent is now dispatched & the template resolution happens at runtime.
  • Fix priority of passed in props vs default props with anonymous components.
  • Add Symfony 7 support.
  • TwigPreLexer: improve performance.
  • Fix twig:lint bug with anonymous component tag.

2.12.0

  • Added a debug:twig-component command.
  • Fixed bad exception when the error comes from a Twig template.
  • Fixed deprecation with TemplateCacheWarmer return type.

2.11.0

  • Support ...spread operator with html syntax (requires Twig 3.7.0 or higher)
  • Add support for anonymous Twig components.
  • Add RenderedComponent::crawler() and toString() methods.
  • Allow a block outside a Twig component to be available inside via outerBlocks.
  • Fix <twig:component> syntax where an attribute is set to an empty value.
  • Add component debug command for TwigComponent and LiveComponent.

2.9.0

  • The ComponentAttributes::defaults() method now accepts any iterable argument. The ComponentAttributes::add() method has been deprecated. To add a Stimulus controller to the attributes, use {{ attributes.defaults(stimulus_controller('...')) }}.

2.8.0

  • Add new HTML syntax for rendering components: <twig:ComponentName>
  • true attribute values now render just the attribute name, false excludes it entirely.
  • Add helpers for testing components.
  • The first argument to AsTwigComponent is now optional and defaults to the class name.
  • Allow passing a FQCN to ComponentFactory methods.

2.7.0

  • PreMount and PostMount hooks can now return nothing.

2.5

  • [BC BREAK] The PreRenderEvent namespace was changed from Symfony\UX\TwigComponent\EventListener to Symfony\UX\TwigComponent\Event.

  • Add new autowireable ComponentRendererInterface

  • Added PostRenderEvent and PreCreateForRenderEvent which are dispatched just before or after a component is rendered.

  • Added PostMountEvent and PreMountEvent which are dispatched just before or after the component's data is mounted.

  • Added Twig template namespaces - #460.

2.2

  • Allow to pass stringable object as non mapped component attribute.
  • Add embedded components.
  • Allow ExposeInTemplate to be used on public component methods.

2.1

  • Make public component properties available directly in the template ({{ prop }} vs {{ this.prop }}).

  • Add PreMount priority parameter.

  • Add PostMount hook component hook to intercept extra props.

  • Add attributes system that takes extra props passed to component() and converts them into a ComponentAttributes object available in your template as attributes.

  • Add PreRenderEvent to intercept/manipulate twig template/variables before rendering.

  • Add ExposeInTemplate attribute to make non-public properties available in component templates directly.

  • Add Computed Properties system.

2.0.0

  • Support for stimulus version 2 was removed and support for @hotwired/stimulus version 3 was added. See the @symfony/stimulus-bridge CHANGELOG for more details.

  • Minimum PHP version was bumped to 8.0 so that PHP 8 attributes could be used.

  • The ComponentInterface was dropped and replaced by the AsTwigComponent attribute. The getComponentName() was replaced by a name argument to the attribute.

Before:

use Symfony\UX\TwigComponent\ComponentInterface;

class AlertComponent implements ComponentInterface
{
    public string $type = 'success';
    public string $message;

    public static function getComponentName(): string
    {
        return 'alert';
    }
}

After:

use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;

#[AsTwigComponent('alert')]
class AlertComponent
{
    public string $type = 'success';
    public string $message;
}
  • If you're using a version lower than Symfony 5.3, you will need to manually tag all component services with twig.component. This is because Symfony 5.3 introduces autoconfiguration for PHP 8 attributes, which this library leverages.

  • The template for a component can now be controlled via the template argument to the AsTwigComponent attribute:

use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;

#[AsTwigComponent('alert', template: 'other/path/alert.html.twig')]
class AlertComponent
{
    // ...
}

Pre-Release

  • The TwigComponent library was introduced!