<p>It's not bad the way you've done it, in my opinion. However I'd probably use an <code>embed</code> instead of an <code>include</code> - that way you can pass in a block of content without having to use <code>set...endset</code>, which sometimes comes with auto-escaping issues, and it just feels a bit cleaner to me:</p>
<pre class="lang-twig prettyprint-override"><code>{# ==================================
Calling template
===================================== #}

{% embed '_ui/components/grid/grid' with {    
    gridCols: gridCols,
    additionalClass: 'c-teaser teasergroup-' ~ variant,
} only %}
    {% block gridItems %}
        &lt;p&gt;All your stuff here&lt;/p&gt;
    {% endblock %}
{% endembed %}

{# ==================================
_ui/components/grid/grid
===================================== #}

{% set gridColsDefault = gridCols[0]|default(1) %}
{% set inheritGridColsSmall = gridCols[1]|default(gridColsDefault) %}
...

&lt;div class=&quot;row row-cols-...&quot;&gt;
    {% block gridItems %}{% endblock %}
    {# or just {{ block('gridItems') }} if you don't need any default content. #}
&lt;/div&gt;
</code></pre>
<p><a href="https://twig.symfony.com/doc/3.x/tags/embed.html" rel="nofollow noreferrer">https://twig.symfony.com/doc/3.x/tags/embed.html</a></p>

CC BY-SA 4.0
2023-10-16T09:25:48.583Z
Ahhh ... I see.

Thank you, James, for explanation!
Marc 
CC BY-SA 4.0
2023-10-14T14:19:49.293Z
2023-10-15T09:20:47.970Z
2023-10-15T09:20:47.970Z
James Smith
<p>First of all: My solution works ... I can not see any problems.<br />
But I'm very unsure whether my code ist a dirty hack or not.</p>
<p>Please don't care about details in my code ... I'm uncertain because:<br />
There is a lot of logic inside <code>{% set teaserItems %}</code>.</p>
<p>Is there a &quot;better&quot; or &quot;cleaner&quot; or &quot;more performant&quot; solution for this?<br />
If not: I'm fine. :)</p>
<pre><code>{# Builds the individual teasers for the grid. #}
{% set teaserItems %}
    {% for item in items %}

        {% set teaser = {
            image: null,
            heading: null,
            text: null,
            button: null,
            link: null,
            overlay: null,
        } %}

        {# Creates the data structure on Teaser or Entry. #}
        {% switch item.type.handle %}

            {% case 'btcTeaserTeaser' %} {# Teaser #}

                {% if item.hasDescendants() %}
                    {% set teaser = teaser|merge({
                        image: {
                            image: item.children[0].assetImage,
                            altText: item.children[0].assetAltText
                        },
                    }) %}
                {% endif %}

                {% if item.heading %}
                    {% set teaser = teaser|merge({
                        heading: {
                            text: item.heading,
                            level: 4
                        },
                    }) %}
                {% endif %}

                {% if item.richTextSimple %}
                    {% set teaser = teaser|merge({
                        text: item.richTextSimple,
                    }) %}
                {% endif %}

                {% if item.linkField.getUrl() %}
                    {% set teaser = teaser|merge({
                        button: item.buttonText|default(_globals.get('moreText')),
                        link: {
                            url: item.linkField.getUrl(),
                            target: item.linkField.target
                        },
                    }) %}
                {% endif %}

            {% case 'btcTeaserEntry' %} {# Entry #}

                {% set entry = item.teaserEntryPreview.one() %}

                {% if entry.entryPreviewImage %}
                    {% set teaser = teaser|merge({
                        image: {
                            image: entry.entryPreviewImage,
                            altText: entry.assetAltText
                        },
                    }) %}
                {% endif %}

                {% if entry.entryPreviewHeading %}
                    {% set teaser = teaser|merge({
                        heading: {
                            text: entry.entryPreviewHeading,
                            level: 4
                        },
                    }) %}
                {% endif %}

                {% if entry.entryPreviewText %}
                    {% set teaser = teaser|merge({
                        text: entry.entryPreviewText,
                    }) %}
                {% endif %}

                {% if entry.url %}
                    {% set teaser = teaser|merge({
                        button: item.buttonText|default(_globals.get('moreText')),
                        link: {
                            url: entry.url,
                        },
                    }) %}
                {% endif %}

        {% endswitch %}

        {# For teaser variant &quot;Overlay&quot;, both BockTypes have this field in common. #}
        {% if item.teaserOverlay %}
            {% set teaser = teaser|merge({
                overlay: item.teaserOverlay,
            }) %}
        {% endif %}

        {# Creates the teaser with the data structure. #}
        {# variant: Variant of the teaser and directory in the path to the template. #}
        &lt;div id=&quot;&quot; class=&quot;col {{ additionalClass|default }}&quot;&gt;
            {% include '_ui/components/teaser/variant/' ~ variant ~ '/teaser-item.twig' with {
                id: pid ~ '-' ~ loop.index,
                variant: 'teaser-' ~ variant,
                teaser: teaser,
                colorSet: item.colorSet,
                ratio: ratio,
                additionalClass: 'h-100',
            } only %}
        &lt;/div&gt;

    {% endfor %}
{% endset %}

{# Build the grid with the teasers. #}
{% include '_ui/components/grid/grid' with {
    gridItems: teaserItems,
    gridCols: gridCols,
    additionalClass: 'c-teaser teasergroup-' ~ variant,
} only %}
</code></pre>
<p><strong>_ui/components/grid/grid</strong></p>
<pre><code>{# inheritance #}
{% set gridColsDefault = gridCols[0]|default(1) %}
{% set inheritGridColsSmall = gridCols[1]|default(gridColsDefault) %}
{% set inheritGridColsMedium = gridCols[2]|default(inheritGridColsSmall) %}
{% set inheritGridColsLarge = gridCols[3]|default(inheritGridColsMedium) %}
{% set inheritGridColsXLarge = gridCols[4]|default(inheritGridColsLarge) %}
{% set inheritGridColsXxLarge = gridCols[5]|default(inheritGridColsXLarge) %}

    &lt;div class=&quot;row row-cols-{{ gridColsDefault }} row-cols-sm-{{ inheritGridColsSmall }} row-cols-md-{{ inheritGridColsMedium }} 
                row-cols-lg-{{ inheritGridColsLarge }} row-cols-xl-{{ inheritGridColsXLarge }} row-cols-xxl-{{ inheritGridColsXxLarge }}
                g-3 {{ additionalClass|default }}&quot;&gt;
    
        {{ gridItems }}
    
    &lt;/div&gt;
</code></pre>

<templating>
twig: loop and switch within set -> dirty code or pragmatic solution
# twig: loop and switch within set -> dirty code or pragmatic solution

(Asked by: username_0 on 2023-10-13)

First of all: My solution works ... I can not see any problems.
But I'm very unsure whether my code ist a dirty hack or not.
Please don't care about details in my code ... I'm uncertain because:
There is a lot of logic inside {% set teaserItems %}.
Is there a "better" or "cleaner" or "more performant" solution for this?
If not: I'm fine. :)
{# Builds the individual teasers for the grid. #}
{% set teaserItems %}
    {% for item in items %}

        {% set teaser = {
            image: null,
            heading: null,
            text: null,
            button: null,
            link: null,
            overlay: null,
        } %}

        {# Creates the data structure on Teaser or Entry. #}
        {% switch item.type.handle %}

            {% case 'btcTeaserTeaser' %} {# Teaser #}

                {% if item.hasDescendants() %}
                    {% set teaser = teaser|merge({
                        image: {
                            image: item.children[0].assetImage,
                            altText: item.children[0].assetAltText
                        },
                    }) %}
                {% endif %}

                {% if item.heading %}
                    {% set teaser = teaser|merge({
                        heading: {
                            text: item.heading,
                            level: 4
                        },
                    }) %}
                {% endif %}

                {% if item.richTextSimple %}
                    {% set teaser = teaser|merge({
                        text: item.richTextSimple,
                    }) %}
                {% endif %}

                {% if item.linkField.getUrl() %}
                    {% set teaser = teaser|merge({
                        button: item.buttonText|default(_globals.get('moreText')),
                        link: {
                            url: item.linkField.getUrl(),
                            target: item.linkField.target
                        },
                    }) %}
                {% endif %}

            {% case 'btcTeaserEntry' %} {# Entry #}

                {% set entry = item.teaserEntryPreview.one() %}

                {% if entry.entryPreviewImage %}
                    {% set teaser = teaser|merge({
                        image: {
                            image: entry.entryPreviewImage,
                            altText: entry.assetAltText
                        },
                    }) %}
                {% endif %}

                {% if entry.entryPreviewHeading %}
                    {% set teaser = teaser|merge({
                        heading: {
                            text: entry.entryPreviewHeading,
                            level: 4
                        },
                    }) %}
                {% endif %}

                {% if entry.entryPreviewText %}
                    {% set teaser = teaser|merge({
                        text: entry.entryPreviewText,
                    }) %}
                {% endif %}

                {% if entry.url %}
                    {% set teaser = teaser|merge({
                        button: item.buttonText|default(_globals.get('moreText')),
                        link: {
                            url: entry.url,
                        },
                    }) %}
                {% endif %}

        {% endswitch %}

        {# For teaser variant "Overlay", both BockTypes have this field in common. #}
        {% if item.teaserOverlay %}
            {% set teaser = teaser|merge({
                overlay: item.teaserOverlay,
            }) %}
        {% endif %}

        {# Creates the teaser with the data structure. #}
        {# variant: Variant of the teaser and directory in the path to the template. #}
        
            {% include '_ui/components/teaser/variant/' ~ variant ~ '/teaser-item.twig' with {
                id: pid ~ '-' ~ loop.index,
                variant: 'teaser-' ~ variant,
                teaser: teaser,
                colorSet: item.colorSet,
                ratio: ratio,
                additionalClass: 'h-100',
            } only %}
        

    {% endfor %}
{% endset %}

{# Build the grid with the teasers. #}
{% include '_ui/components/grid/grid' with {
    gridItems: teaserItems,
    gridCols: gridCols,
    additionalClass: 'c-teaser teasergroup-' ~ variant,
} only %}

_ui/components/grid/grid
{# inheritance #}
{% set gridColsDefault = gridCols[0]|default(1) %}
{% set inheritGridColsSmall = gridCols[1]|default(gridColsDefault) %}
{% set inheritGridColsMedium = gridCols[2]|default(inheritGridColsSmall) %}
{% set inheritGridColsLarge = gridCols[3]|default(inheritGridColsMedium) %}
{% set inheritGridColsXLarge = gridCols[4]|default(inheritGridColsLarge) %}
{% set inheritGridColsXxLarge = gridCols[5]|default(inheritGridColsXLarge) %}

    
    
        {{ gridItems }}

**Tags:** templating


---

## 1 answers

### Answer by username_1 on 2023-10-14. Score: 1

It's not bad the way you've done it, in my opinion. However I'd probably use an embed instead of an include - that way you can pass in a block of content without having to use set...endset, which sometimes comes with auto-escaping issues, and it just feels a bit cleaner to me:
{# ==================================
Calling template
===================================== #}

{% embed '_ui/components/grid/grid' with {    
    gridCols: gridCols,
    additionalClass: 'c-teaser teasergroup-' ~ variant,
} only %}
    {% block gridItems %}
        All your stuff here
    {% endblock %}
{% endembed %}

{# ==================================
_ui/components/grid/grid
===================================== #}

{% set gridColsDefault = gridCols[0]|default(1) %}
{% set inheritGridColsSmall = gridCols[1]|default(gridColsDefault) %}
...


    {% block gridItems %}{% endblock %}
    {# or just {{ block('gridItems') }} if you don't need any default content. #}


https://twig.symfony.com/doc/3.x/tags/embed.html

> **Comments:**
> **username_0**: Ahhh ... I see.  Thank you, James, for explanation!  

---

