-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Add an html_attr function to make outputting HTML attributes easier
#3930
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 3.x
Are you sure you want to change the base?
Changes from all commits
3f66969
ecf5398
f8e8a78
a907d64
8453365
07af6b9
3a42243
566709d
3d72b6e
9fb1a62
b160329
8c28d31
820f2d9
8d48f7f
16375f9
61efd43
5fd4669
848f512
8eb7362
8469476
fe23507
825ed79
3340417
b4e2ef7
7ba55b6
a621892
58428e7
dfdef61
47aa33e
5616efd
90a4d20
ac688b7
492ebae
eb9e82b
297f13a
887293d
cab3745
f943dc8
714917e
54b5760
28ac687
5e8200e
dd5b6b7
ef86676
d6f7da3
d19b7f2
b15bb4c
4b89a8a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| ``html_attr_merge`` | ||
| =================== | ||
|
|
||
| .. _html_attr_merge: | ||
|
|
||
| .. versionadded:: 3.24 | ||
|
|
||
| The ``html_attr_merge`` filter was added in Twig 3.24. | ||
|
|
||
| The ``html_attr_merge`` filter merges multiple mappings that represent | ||
| HTML attribute values. Such mappings contain the names of the HTML attributes | ||
| as keys, and the corresponding values represent the attributes' values. | ||
|
|
||
| It is primarily designed for working with arrays that are passed to the | ||
| :ref:`html_attr` function. It closely resembles the :doc:`merge <../filters/merge>` | ||
| filter, but has different merge behavior for values that are iterables | ||
| themselves, as it will merge such values in turn. | ||
|
|
||
| The filter returns a new merged array: | ||
|
|
||
| .. code-block:: twig | ||
|
|
||
| {% set base = {class: ['btn'], type: 'button'} %} | ||
| {% set variant = {class: ['btn-primary'], disabled: true} %} | ||
|
|
||
| {% set merged = base|html_attr_merge(variant) %} | ||
|
|
||
| {# merged is now: { | ||
| class: ['btn', 'btn-primary'], | ||
| type: 'button', | ||
| disabled: true | ||
| } #} | ||
|
|
||
| The filter accepts multiple arrays as arguments and merges them from left to right: | ||
|
|
||
| .. code-block:: twig | ||
|
|
||
| {% set merged = base|html_attr_merge(variant1, variant2, variant3) %} | ||
|
|
||
| A common use case is to build attribute mappings conditionally by merging multiple | ||
| parts based on conditions. To make this conditional merging more convenient, filter | ||
| arguments that are ``false``, ``null`` or empty arrays are ignored: | ||
|
|
||
| .. code-block:: twig | ||
|
|
||
| {% set button_attrs = { | ||
| type: 'button', | ||
| class: ['btn'] | ||
| }|html_attr_merge( | ||
| variant == 'primary' ? { class: ['btn-primary'] }, | ||
| variant == 'secondary' ? { class: ['btn-secondary'] }, | ||
| size == 'large' ? { class: ['btn-lg'] }, | ||
| size == 'small' ? { class: ['btn-sm'] }, | ||
| disabled ? { disabled: true, class: ['btn-disabled'] }, | ||
| loading ? { 'aria-busy': 'true', class: ['btn-loading'] }, | ||
| ) %} | ||
|
|
||
| {# Example with variant='primary', size='large', disabled=false, loading=true: | ||
|
|
||
| The false values (secondary variant, small size, disabled state) are ignored. | ||
|
|
||
| button_attrs is: | ||
| { | ||
| type: 'button', | ||
| class: ['btn', 'btn-primary', 'btn-lg', 'btn-loading'], | ||
| 'aria-busy': 'true' | ||
| } | ||
| #} | ||
|
|
||
| Merging Rules | ||
mpdude marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ------------- | ||
|
|
||
| The filter follows these rules when merging attribute values: | ||
|
|
||
| **Scalar values**: Later values override earlier ones. | ||
|
|
||
| .. code-block:: twig | ||
|
|
||
| {% set result = {id: 'old'}|html_attr_merge({id: 'new'}) %} | ||
| {# result: {id: 'new'} #} | ||
|
|
||
| **Array values**: Arrays are merged like in PHP's ``array_merge`` function - numeric keys are | ||
| appended, non-numeric keys replace. | ||
mpdude marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| .. code-block:: twig | ||
|
|
||
| {# Numeric keys (appended): #} | ||
| {% set result = {class: ['btn']}|html_attr_merge({class: ['btn-primary']}) %} | ||
| {# result: {class: ['btn', 'btn-primary']} #} | ||
|
|
||
| {# Non-numeric keys (replaced): #} | ||
| {% set result = {class: {base: 'btn', size: 'small'}}|html_attr_merge({class: {variant: 'primary', size: 'large'}}) %} | ||
| {# result: {class: {base: 'btn', size: 'large', variant: 'primary'}} #} | ||
|
|
||
| .. note:: | ||
|
|
||
| Remember, attribute mappings passed to or returned from this filter are regular | ||
| Twig mappings after all. If you want to completely replace an attribute value | ||
| that is an iterable with another value, you can use the :doc:`merge <../filters/merge>` | ||
| filter to do that. | ||
|
|
||
| **``MergeableInterface`` implementations**: For advanced use cases, attribute values can be objects | ||
| that implement the ``MergeableInterface``. These objects can define their own, custom merge | ||
| behavior that takes precedence over the default rules. See the docblocks in that interface | ||
| for details. | ||
|
|
||
| .. note:: | ||
|
|
||
| The ``html_attr_merge`` filter is part of the ``HtmlExtension`` which is not | ||
| installed by default. Install it first: | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| $ composer require twig/html-extra | ||
|
|
||
| Then, on Symfony projects, install the ``twig/extra-bundle``: | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| $ composer require twig/extra-bundle | ||
|
|
||
| Otherwise, add the extension explicitly on the Twig environment:: | ||
|
|
||
| use Twig\Extra\Html\HtmlExtension; | ||
|
|
||
| $twig = new \Twig\Environment(...); | ||
| $twig->addExtension(new HtmlExtension()); | ||
|
|
||
| Arguments | ||
| --------- | ||
|
|
||
| The filter accepts a variadic list of arguments to merge. Each argument can be: | ||
|
|
||
| * A map of attributes | ||
| * ``false`` or ``null`` (ignored, useful for conditional merging) | ||
| * An empty string ``''`` (ignored, to support implicit else in ternary operators) | ||
|
|
||
| .. seealso:: | ||
|
|
||
| :ref:`html_attr`, | ||
| :doc:`html_attr_type` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| ``html_attr_type`` | ||
| ================== | ||
|
|
||
| .. _html_attr_type: | ||
|
|
||
| .. versionadded:: 3.24 | ||
|
|
||
| The ``html_attr_type`` filter was added in Twig 3.24. | ||
|
|
||
| The ``html_attr_type`` filter converts arrays into specialized attribute value | ||
| objects that implement custom rendering logic. It is designed for use | ||
| with the :ref:`html_attr` function for attributes where | ||
| the attribute value follows special formatting rules. | ||
|
|
||
| .. code-block:: html+twig | ||
|
|
||
| <img {{ html_attr({ | ||
| srcset: ['small.jpg 480w', 'large.jpg 1200w']|html_attr_type('cst') | ||
| }) }}> | ||
|
|
||
| {# Output: <img srcset="small.jpg 480w, large.jpg 1200w"> #} | ||
|
|
||
| Available Types | ||
| --------------- | ||
|
|
||
| Space-Separated Token List (``sst``) | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| Used for attributes that expect space-separated values, like ``class`` or | ||
| ``aria-labelledby``: | ||
|
|
||
| .. code-block:: html+twig | ||
|
|
||
| {% set classes = ['btn', 'btn-primary']|html_attr_type('sst') %} | ||
|
|
||
| <button {{ html_attr({class: classes}) }}> | ||
| Click me | ||
| </button> | ||
|
|
||
| {# Output: <button class="btn btn-primary">Click me</button> #} | ||
|
|
||
| This is the default type used when the :ref:`html_attr` function encounters an | ||
| array value (except for ``style`` attributes). | ||
|
|
||
| Comma-Separated Token List (``cst``) | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| Used for attributes that expect comma-separated values, like ``srcset`` or | ||
| ``sizes``: | ||
|
|
||
| .. code-block:: html+twig | ||
|
|
||
| <img {{ html_attr({ | ||
| srcset: ['image-1x.jpg 1x', 'image-2x.jpg 2x', 'image-3x.jpg 3x']|html_attr_type('cst'), | ||
| sizes: ['(max-width: 600px) 100vw', '50vw']|html_attr_type('cst') | ||
| }) }}> | ||
|
|
||
| {# Output: <img srcset="image-1x.jpg 1x, image-2x.jpg 2x, image-3x.jpg 3x" sizes="(max-width: 600px) 100vw, 50vw"> #} | ||
|
|
||
| Inline Style (``style``) | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| Used for style attributes. Handles both maps (property - value pairs) and sequences (CSS declarations): | ||
|
|
||
| .. code-block:: html+twig | ||
|
|
||
| {# Associative array #} | ||
| {% set styles = {color: 'red', 'font-size': '14px'}|html_attr_type('style') %} | ||
|
|
||
| <div {{ html_attr({style: styles}) }}> | ||
| Styled content | ||
| </div> | ||
|
|
||
| {# Output: <div style="color: red; font-size: 14px;">Styled content</div> #} | ||
|
|
||
| {# Numeric array #} | ||
| {% set styles = ['color: red', 'font-size: 14px']|html_attr_type('style') %} | ||
|
|
||
| <div {{ html_attr({style: styles}) }}> | ||
| Styled content | ||
| </div> | ||
|
|
||
| {# Output: <div style="color: red; font-size: 14px;">Styled content</div> #} | ||
|
|
||
| The ``style`` type is automatically applied by the :ref:`html_attr` function when | ||
| it encounters an array value for the ``style`` attribute. | ||
|
Comment on lines
+85
to
+86
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would have been the case for both previous example, no? I mean, what would happen to both examples without the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it would, because of the default handling of attributes named TBH I am not sure if this type should be exposed in the first place. WDYT – do you see any situation where one might want to have inline CSS in another attribute? That could be used to improve this section. |
||
|
|
||
| .. note:: | ||
|
|
||
| The ``html_attr_type`` filter is part of the ``HtmlExtension`` which is not | ||
| installed by default. Install it first: | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| $ composer require twig/html-extra | ||
|
|
||
| Then, on Symfony projects, install the ``twig/extra-bundle``: | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| $ composer require twig/extra-bundle | ||
|
|
||
| Otherwise, add the extension explicitly on the Twig environment:: | ||
|
|
||
| use Twig\Extra\Html\HtmlExtension; | ||
|
|
||
| $twig = new \Twig\Environment(...); | ||
| $twig->addExtension(new HtmlExtension()); | ||
|
|
||
| Arguments | ||
| --------- | ||
|
|
||
| * ``value``: The sequence of attributes to convert | ||
| * ``type``: The attribute type. One of: | ||
|
|
||
| * ``sst`` (default): Space-separated token list | ||
| * ``cst``: Comma-separated token list | ||
| * ``style``: Inline CSS styles | ||
|
|
||
| .. seealso:: | ||
|
|
||
| :ref:`html_attr`, | ||
| :ref:`html_attr_merge` | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation for those functions and filters should include the note about the fact that they are part of an extra extension, not of Twig core (see the documentation of the
html_classesfunction or thedata_urifilter for existing usages)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I see that it is actually present inside the section about merging rules. This is confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's always at the end of the documentation pages, like for example with
html_cva– those other pages also have other preceding sub-headlines.