<p>Another (probably better/simpler) solution, inspired by @JamesSmith's comment, uses <code>embed</code> to avoid includes inside of macros, and has all the same flexibility:</p>
<p><strong>file.twig</strong></p>
<pre><code>{% set entries = craft.entries({ section: 'events').all() %}
{% embed &quot;/_partials/tiles.twig&quot; with {'entries':entries}  %}
    {% block captionContent %}
        &lt;h1&gt;{{entry.title}}&lt;/h2&gt;
        &lt;p class='datestamp'&gt;{{entry.eventDate | date('yy/m/d')}}&lt;/p&gt;
        &lt;p&gt;{{entry.lead}}&lt;/p&gt;
    {% endblock %}  
{% endembed %}
</code></pre>
<p><strong>/_partials/tiles.twig</strong></p>
<pre><code>&lt;div&gt;
    {%- for entry in entries %}
        &lt;div&gt;
            {% block captionContent %}
                {# Default Content Overridden by 'embed'/'block' Call  #}
                &lt;p&gt;Hello World!&lt;/p&gt;
            {% endblock %}
        &lt;/div&gt;
    {% endfor -%}
&lt;/div&gt;
</code></pre>
<p>This way the <code>block</code> is called on the loop as if it was in scope of the parent page and overrides the default content inside. But if the block is not provided then the default content inside each loop is displayed.</p>

CC BY-SA 4.0
2022-09-23T17:21:56.597Z
2022-09-23T17:21:56.597Z
Adrian
<p>Answering my own question...
So in my search I was looking for a twig way to do something similar to php's eval and  came across the <a href="https://twig.symfony.com/doc/2.x/functions/template_from_string.html" rel="nofollow noreferrer">twig function</a> <code>template_from_string()</code></p>
<p>The sample code from twig's docs looks like this: <code>{{ include(template_from_string(&quot;Hello {{ name }}&quot;)) }}</code></p>
<p>So I can create a string in my <code>file.twig</code> that's eval'd only when it's &quot;included&quot; in <code>macros.twig</code>.</p>
<p><strong>Here is what that looks like:</strong></p>
<p><strong>file.twig</strong></p>
<pre><code>{% set entries = craft.entries({ section: 'events').all() %}
{% set tileContent = template_from_string(&quot;&lt;p&gt;{{tileEntry.title}}&lt;/p&gt;&quot;) %}
{% import &quot;macros.twig&quot; as generalMacros %}
{{ generalMacros.renderTile(entries, tileContent) }}
</code></pre>
<p><strong>macros.twig</strong></p>
<pre><code>{% macro renderTile(entries, tileContent) %}
  {%- for tileEntry in entries %}
    &lt;div&gt;
        {{include(tileContent)}}
    &lt;/div&gt;
  {% endfor -%}
{% endmacro %}

</code></pre>
<p>This way the variable string <code>tileContent</code> is not actually evaluated in context until it's &quot;included&quot; in <code>macros.twig</code> when we output <code>{{include(tileContent)}}</code>.</p>

CC BY-SA 4.0
2022-09-19T18:39:44.873Z
Feels like you might be over-complicating things here? Have you tried using an `embed`? https://twig.symfony.com/doc/3.x/tags/embed.html
James Smith
CC BY-SA 4.0
2022-09-23T13:13:31.120Z
@JamesSmith — Well hot damn!!! That is much simpler. Thank you! — I'll post another answer with a refactored solution using `embed`
Adrian
CC BY-SA 4.0
2022-09-19T05:20:41.277Z
2022-09-19T05:27:48.887Z
2022-09-19T05:27:48.887Z
Adrian
<p>I have a slightly mind bending question. Here's my setup:</p>
<p><strong>file.twig</strong></p>
<pre><code>{% set entries = craft.entries({ section: 'events').all() %}
{% set tileContent %}
    &lt;p&gt;{{tileEntry.title}}&lt;/p&gt;
{% endset %}
{% import &quot;macros.twig&quot; as generalMacros %}
{{ generalMacros.renderTile(entries, tileContent) }}
</code></pre>
<p><strong>macros.twig</strong></p>
<pre><code>{% macro renderTile(entries, tileContent) %}
  {%- for tileEntry in entries %}
    &lt;div&gt;
        {{tileContent}}
    &lt;/div&gt;
  {% endfor -%}
{% endmacro %}

</code></pre>
<p>So my macro variable <code>tileContent</code> contains <code>tileEntry.title</code>, which refers to the <code>tileEntry</code> generated in the macro's <code>for</code> loop.</p>
<p>However, when I run this, the variable of <code>tileEntry</code> is not picked up in the macro's loop, and so nothing is output - in fact I get an error that <code>tileEntry</code> isn't defined... which is correct as it's defined inside the <code>for</code> loop inside <code>macros.twig</code></p>
<p>I can't seem to pass a variable to a macro that contains a reference to a variable generated by that macro... oy.</p>
<p><strong>Why do I want to do this?</strong></p>
<p>So that we never have to edit <strong>macros.twig</strong> — all we need to do is edit <strong>file.twig</strong> and pass it content through the variable <code>{{tileContent}}</code> and use variables inside the macro to customize it.</p>
<p>Basically the contents of <code>tileContent</code> are being interpreted before they are being sent to the macro, whereas I'd like it to be interpreted inside the macro first.</p>
<p>Is what I am trying to do even possible? And if so, how would you go about it?</p>

<variable><macro><craft4>
Macros: Variables inside of variables
# Macros: Variables inside of variables

(Asked by: username_0 on 2022-09-19)

I have a slightly mind bending question. Here's my setup:
file.twig
{% set entries = craft.entries({ section: 'events').all() %}
{% set tileContent %}
    {{tileEntry.title}}
{% endset %}
{% import "macros.twig" as generalMacros %}
{{ generalMacros.renderTile(entries, tileContent) }}

macros.twig
{% macro renderTile(entries, tileContent) %}
  {%- for tileEntry in entries %}
    
        {{tileContent}}
    
  {% endfor -%}
{% endmacro %}


So my macro variable tileContent contains tileEntry.title, which refers to the tileEntry generated in the macro's for loop.
However, when I run this, the variable of tileEntry is not picked up in the macro's loop, and so nothing is output - in fact I get an error that tileEntry isn't defined... which is correct as it's defined inside the for loop inside macros.twig
I can't seem to pass a variable to a macro that contains a reference to a variable generated by that macro... oy.
Why do I want to do this?
So that we never have to edit macros.twig — all we need to do is edit file.twig and pass it content through the variable {{tileContent}} and use variables inside the macro to customize it.
Basically the contents of tileContent are being interpreted before they are being sent to the macro, whereas I'd like it to be interpreted inside the macro first.
Is what I am trying to do even possible? And if so, how would you go about it?

**Tags:** variable, macro, craft4

---

## 2 answers

### Answer by username_0 on 2022-09-23. Score: 0 | Accepted answer

Another (probably better/simpler) solution, inspired by @JamesSmith's comment, uses embed to avoid includes inside of macros, and has all the same flexibility:
file.twig
{% set entries = craft.entries({ section: 'events').all() %}
{% embed "/_partials/tiles.twig" with {'entries':entries}  %}
    {% block captionContent %}
        {{entry.title}}
        {{entry.eventDate | date('yy/m/d')}}
        {{entry.lead}}
    {% endblock %}  
{% endembed %}

/_partials/tiles.twig

    {%- for entry in entries %}
        
            {% block captionContent %}
                {# Default Content Overridden by 'embed'/'block' Call  #}
                Hello World!
            {% endblock %}
        
    {% endfor -%}


This way the block is called on the loop as if it was in scope of the parent page and overrides the default content inside. But if the block is not provided then the default content inside each loop is displayed.


---

### Answer by username_0 on 2022-09-19. Score: 0

Answering my own question...
So in my search I was looking for a twig way to do something similar to php's eval and  came across the twig function template_from_string()
The sample code from twig's docs looks like this: {{ include(template_from_string("Hello {{ name }}")) }}
So I can create a string in my file.twig that's eval'd only when it's "included" in macros.twig.
Here is what that looks like:
file.twig
{% set entries = craft.entries({ section: 'events').all() %}
{% set tileContent = template_from_string("{{tileEntry.title}}") %}
{% import "macros.twig" as generalMacros %}
{{ generalMacros.renderTile(entries, tileContent) }}

macros.twig
{% macro renderTile(entries, tileContent) %}
  {%- for tileEntry in entries %}
    
        {{include(tileContent)}}
    
  {% endfor -%}
{% endmacro %}


This way the variable string tileContent is not actually evaluated in context until it's "included" in macros.twig when we output {{include(tileContent)}}.

> **Comments:**
> **username_1**: Feels like you might be over-complicating things here? Have you tried using an `embed`? https://twig.symfony.com/doc/3.x/tags/embed.html  
> **username_0**: @JamesSmith — Well hot damn!!! That is much simpler. Thank you! — I'll post another answer with a refactored solution using `embed`  

---

