Search code examples
shopify-template

Variable scope in Shopify Sections


I'm trying to use a variable in my section file but it doesn't appear to be inherited from it's parent template.

For example:

index.liquid

{% assign foo = "bar" %}
{% section 'example' %}

sections/example.liquid

<h1>{{ foo }}</h1>

{% schema %}
{
    "name": "Example",
    "settings": [
       ...
    ]
}
{% endschema %}

It will not output the value of {{ foo }}, instead I just get: <h1></h1> as if the variable was never defined.

I thought sections would work like snippets, where anything defined in the parent template would be in scope in the included snippet:

index.liquid

{% assign foo = "bar" %}
{% include 'example' %}

snippets/example.liquid

<h1>{{ foo }}</h1>

Where I would get <h1>bar</h1> when rendered.

  • Is this a bug, or intended behaviour?
  • Is there a way I can include a section and use variable from some form of outer-scope?

Thanks!


Solution

  • If this is intended behaviour, I managed to find a way round it and thought I would post my not-perfect but workable solution:

    sections/example.liquid

    <h1><!-- foo --></h1>
    

    You can use capture, to get the contents of the section as a string and use string filters on the captured markup:

    index.liquid

    {% assign foo = "bar" %}
    {% capture section %}{% section 'example' %}{% endcapture %}
    {{ section | replace: '<!-- foo -->', foo }}
    

    You could of course replace any string, with your variable. But I found HTML comments work well because if you forget to run the replace, or don't need to - nothing is rendered.

    If you wanted to do something more complex, like remove some markup from the section you could:

    sections/example.liquid

    <div>
    
        <!-- REMOVE_TITLE? -->
        <h1>{{ section.settings.title }}</h1>
        <!-- REMOVE_TITLE? -->
    
        <ul>
            {% for block in section.blocks %}
                <li>{{ block.settings.image | img_url: '300x' | img_tag }}</li>
            {% endfor %}
        </ul>
    </div>
    

    Then you could do something like:

    {% capture section %}{% section 'example' %}{% endcapture %}
    {% assign parts = section | split: '<!-- REMOVE_TITLE? -->' %}
    {% for part in parts %}
        {% assign mod = forloop.index | modulo: 2 %}
        {% if mod > 0 %}{{ part }}{% endif %}
    {% endfor %}