Skip to content
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

Add an attr function to make outputting HTML attributes easier #3930

Draft
wants to merge 2 commits into
base: 3.x
Choose a base branch
from

Conversation

mpdude
Copy link
Contributor

@mpdude mpdude commented Dec 6, 2023

Here is a quick PoC for #3907.

First, it adds a attr_merge filter. This filter is intended to be used with arrays that represent HTML attribute name-value pairs. Basically, it works like |merge, but for the special key names class, style and data it performs merging on the value level.

This is intended for the use case where you'd like to add to the attributes for an HTML element based on conditions, e. g. multiple subsequent {% if ... %} blocks.

Example:

  • { class: 'foo' }|attr_merge({ class: 'bar' }) will be { class: ['foo', 'bar'] }
  • { class: 'foo' }|attr_merge({ class: ['bar', 'baz'] }) will be { class: ['foo', 'bar', 'baz'] }
  • { class: { special: 'foo' } }|attr_merge({ class: ['bar', 'baz'] })|attr_merge({ class: {special: 'qux' } }) will be { class: { special: 'qux', 0: 'bar', 1: 'baz' } }

or in Twig code:

{% set attr = attr ?? {} %}
{% if condition1 %}
  {% set attr = attr|attr_merge({ class: 'foo', data: { condition1: 'met' }) %}
{% endif %}
{% if condition2 %}
  {% set attr = attr|attr_merge({ class: 'bar', data: { condition2: 'met' }) %}
{% endif %}

Second, it adds a attr function. This function takes one or multiple attr arrays like above, and print them as a series of HTML attribute markup. All values from class will be concatenated with spaces. Key/value pairs from style will be treated as CSS property/value pairs. For data, keys will be used to construct data-{keyname} attributes.

Example:


    {% set id = 'id value' %}
    {% set href = 'href value' %}
    {% set disabled = true %}

    <div {{ attr(
        { id, href },
        disabled ? { 'aria-disabled': 'true' },
        not disabled ? { 'aria-enabled' : true },
        { class: ['zero', 'first'] },
        { class: 'second' },
        true ? { class: 'third' },
        { style: { color: 'red' } },
        { style: { 'background-color': 'green' } },
        { style: { color: 'blue' } },
        { 'data-test': 'some value' },
        { data: { test: 'other value', bar: 'baz' }},
        { 'dangerous=yes foo' : 'xss' },
        { style: 'font-weight: bold' },
        { style: ['text-decoration: underline'] },
    ) }}></div>

will generate HTML markup:

<div id="id value" href="href%20value" aria-disabled="true" data-test="other value" data-bar="baz" dangerous&#x3D;yes&#x20;foo="xss" class="zero first second third" style="color: red; background-color: green; color: blue; font-weight: bold; text-decoration: underline;"></div>

TODO:

  • Get initial feedback
  • Add tests
  • Add documentation
  • Add docblocks

@mpdude mpdude marked this pull request as draft December 6, 2023 22:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant