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) }} /> ```
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.twigtemplate fallback when resolving namespaced anonymous components - Add support for dynamic template resolution with
AsTwigComponent(template: FromMethod('getCustomFuntion'))
2.32
- Add option
profiler.collect_componentsto 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
ComponentAttributesrendering when usingStimulusAttributesas default attributes
2.25.1
- [SECURITY]
ComponentAttributesnow requires aTwig\Runtime\EscaperRuntimeinstance as second argument - Remove
HtmlAttributeEscaperInterface,TwigHtmlAttributeEscaperandComponentAttributesFactory
2.25.0
- [SECURITY] Make
ComponentAttributesresponsible for attribute escaping ensuring consistent and secure HTML output across all rendering contexts - Deprecate not passing an
HtmlAttributeEscaperInterfaceto theComponentAttributesconstructor
2.20.0
- Add Anonymous Component support for 3rd-party bundles #2019
- Deprecate
cvaTwig function in favor ofhtml_cvafromtwig/html-extra#2144
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
attributesvariable #1442 - Restrict Twig 3.9 for now #1486
- Build reproducible TemplateMap to fix possible post-deploy breakage #1497
2.14.0
- Make
ComponentAttributestraversable/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
PreMountEventandPostMountEvent - Added configuration to separate your components into different "namespaces"
- Add
outerScopevariable reach variables from the parent template of an "embedded" component. - Deprecate calling
ComponentTemplateFinderconstructor withoutdirectoryargument. - Add profiler integration:
TwigComponentDataCollectorand debug toolbar templates - Add search feature in
debug:twig-componentcommand. - Fix inconsistencies with how
{% component %}/<twig:component>syntaxes are rendered vscomponent():PostRenderEventis 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-componentcommand. - Fixed bad exception when the error comes from a Twig template.
- Fixed deprecation with
TemplateCacheWarmerreturn 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()andtoString()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. TheComponentAttributes::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> trueattribute values now render just the attribute name,falseexcludes it entirely.- Add helpers for testing components.
- The first argument to
AsTwigComponentis now optional and defaults to the class name. - Allow passing a FQCN to
ComponentFactorymethods.
2.7.0
PreMountandPostMounthooks can now return nothing.
2.5
-
[BC BREAK] The
PreRenderEventnamespace was changed fromSymfony\UX\TwigComponent\EventListenertoSymfony\UX\TwigComponent\Event. -
Add new autowireable
ComponentRendererInterface -
Added
PostRenderEventandPreCreateForRenderEventwhich are dispatched just before or after a component is rendered. -
Added
PostMountEventandPreMountEventwhich 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
ExposeInTemplateto be used on public component methods.
2.1
-
Make public component properties available directly in the template (
{{ prop }}vs{{ this.prop }}). -
Add
PreMountpriority parameter. -
Add
PostMounthook component hook to intercept extra props. -
Add attributes system that takes extra props passed to
component()and converts them into aComponentAttributesobject available in your template asattributes. -
Add
PreRenderEventto intercept/manipulate twig template/variables before rendering. -
Add
ExposeInTemplateattribute to make non-public properties available in component templates directly. -
Add Computed Properties system.
2.0.0
-
Support for
stimulusversion 2 was removed and support for@hotwired/stimulusversion 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
ComponentInterfacewas dropped and replaced by theAsTwigComponentattribute. ThegetComponentName()was replaced by anameargument 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
templateargument to theAsTwigComponentattribute:
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
#[AsTwigComponent('alert', template: 'other/path/alert.html.twig')]
class AlertComponent
{
// ...
}
Pre-Release
- The TwigComponent library was introduced!