Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 517
chrishale Avatar asked Sep 23 '26 02:09

chrishale


2 Answers

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 %}
like image 51
chrishale Avatar answered Sep 26 '26 01:09

chrishale


I would assign all your variables in a snippet and the keep including this same snippet in whichever scope you need to use the variables in....

That is a fairly DRY approach.

Also anything defined in config/settings_schema.json has a global scope but it can be given new values in theme settings by end users.

like image 22
Daniel Eisen Avatar answered Sep 26 '26 01:09

Daniel Eisen