Twig

The flexible, fast, and secure
template engine for PHP

a Symfony Product
Docs Filters html_attr_merge
Docs for Twig version 3.x
Switch to another version: 1.x, 2.x

Table of Contents

Questions & Feedback

License

Twig documentation is licensed under the new BSD license.

html_attr_merge

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 html_attr function. It closely resembles the 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:

1
2
3
4
5
6
7
8
9
10
{% 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:

1
{% 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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{% 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

The filter follows these rules when merging attribute values:

Scalar values: Later values override earlier ones.

1
2
{% 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.

1
2
3
4
5
6
7
{# 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 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:

1
$ composer require twig/html-extra

Then, on Symfony projects, install the twig/extra-bundle:

1
$ composer require twig/extra-bundle

Otherwise, add the extension explicitly on the Twig environment:

1
2
3
4
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)