Re: How Can I render a snippet this name is defined by a variable?

How Can I render a snippet this name is defined by a variable?

masahiro
Shopify Partner
9 0 2

I want to render a snippet this name is defined by a variable.

 

 

{% assign template_name = 'page-' | append: page.template_suffix %}
{% render template_name %}

But it occurs error that show "Syntax error in tag 'render' - Template name must be a quoted string".

 

"include" tag can render a snippet this name is defined by a variable.

 

Why "render" tag can't do it?

 

Replies 13 (13)

Visely-Team
Shopify Partner
1843 210 488

Unfortunately, render doesn't accept dynamic names, most probably by design and taking into consideration the performance impact. 

Sergiu Svinarciuc | CTO @ visely.io
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution!
- To learn more about the awesome stuff we do head over to visely.io or our blog
jacobgraf
Shopify Partner
13 0 12

Well, that's a bummer! This would have saved me from having to create a bunch of individual templates. 😫

diego_ezfy
Shopify Partner
2988 573 931

@Visely-Team @masahiro @jacobgraf 

Would you happen to know any alternatives for this? 

Thank you!

â—¦ Search for text across all files in your Shopify theme
â—¦ Proudly top #5 Shopify Expert of all time - Book a call with me here.
Visely-Team
Shopify Partner
1843 210 488

@diego_ezfy nope, not to my knowledge.

Sergiu Svinarciuc | CTO @ visely.io
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution!
- To learn more about the awesome stuff we do head over to visely.io or our blog
jacobgraf
Shopify Partner
13 0 12

I ended up double-checking with Shopify to make sure "include" wouldn't be deprecated. They confirmed they have no plans to deprecate it, so, for now, this is the solution I came up with and it works great! This approach will not work with "render".

 

<!-- Product-Specific Content -->
{% assign snippet = 'product-content-' | append: product.handle %}
{% capture snippet_content %}{% include snippet %}{% endcapture %}
{% unless snippet_content contains "Liquid error" %}
    {{ snippet_content }}
{% endunless %}

 

flavioccf
Shopify Partner
2 0 9

I used this workaround, by appending an empty string the variable name is transformed into a string.

 

{%- render variable_name | append: "" -%}

 

TheLankyCoder
Shopify Partner
3 0 1

Perfect. That worked for me. Thank you.

Dylan_Thacker-S
Shopify Staff (Retired)
11 0 3

That workaround is clearly relying on a bug. Intentionally relying on a bug is fragile to changes we make to liquid or Shopify's extensions to liquid, since it puts you code at risk from breaking from a bug fix.

To learn more visit the Shopify Help Center or the Community Blog.

flavioccf
Shopify Partner
2 0 9

Thanks, Dylan, it was NOT clearly intentional. Since `render` only allows strings I was simply transforming the variable into a string (because the variable is a string already) . I also saw that you were very quick to fix the bug on Github.

My use case was simple, I had a list of icon snippets that could be selected in a section. 

{% assign snippet_name = section.settings.snippet_name %}
{% include snippet_name %}

 

In order to achieve the same result with `render` I will have to use a switch case or something similar that will make the code way more verbose.

{% assign snippet_name = section.settings.snippet_name %}
{% case snippet_name %}
  {% when "snippet_1" %}
     {% render "snippet_1" %}
  {% when "snippet_2" %}
     {% render "snippet_2" %}
  {% when "snippet_3" %}
     {% render "snippet_3" %}
...
...
...
...
{% endcase %}

 


But thank you again for the clarification and for fixing the bug so fast.

Dylan_Thacker-S
Shopify Staff (Retired)
11 0 3

I'm sorry that I jumped to conclusions about your intentions with the workaround.  I suppose you are not aware that the render tag doesn't have a filter.  Liquid is still not strict enough to make this clear to the author, since although sections are parsed in a stricter mode, this now means we need multiple levels of strictness to warn about these problems in a backwards compatible way.  Specifically, the lack of strictness comes from unanchored regex matching for the tag syntax.

 

Why "render" tag can't do it?

 

The primary reason for the restriction is to enable better performance optimizations by being able to statically determine the dependencies for the liquid template, to better allow the code and data needed to render the template to be batch loaded upfront.  Dynamic template loading could potentially also be a concern for readability of the liquid code, where it makes it less clear what snippet it could/should depend on.

 

In order to achieve the same result with `render` I will have to use a switch case or something similar that will make the code way more verbose.

 

Where possibly, consider whether this can be made less dynamic.  For instance, passing variables to a snippet is one possible way of passing something dynamic into a snippet.

 

If a truly dynamic render is needed, then a case tag is definitely an alternative.  I wouldn't expect this would need to support all the snippets as possible targets for an include, which could reduce the verbosity and make it clearer which snippets are actually intended to possibly be rendered from that tag (e.g. your icon snippets).  If this dynamic render is actually needed in multiple places, then it would also be possible to avoid this duplication by moving this case tag to a generic snippet for that use case (e.g. generic icon snippet), where it can be passed a variable to to indicate which snippet to render (e.g. icon name).

To learn more visit the Shopify Help Center or the Community Blog.

deimos_ind
Shopify Partner
2 0 0

How about this use case?

{%- assign icons = 'handmade,handraised,fluted,made-shoppe,made-borough,made-charnwood' | split: ',' -%}
{%- for icon in icons -%}
<li>
{%- render 'icon-' | append: icon -%}
</li>
{%- endfor -%}

You can statically define which files are being imported, I can do the below in Twig but not in Liquid

 

{% var icons = ['handmade', 'handraised', 'fluted', 'made-shoppe', 'made-borough', 'made-charnwood'] %}
{% for icon in icons %}
<li>
{% include 'icon-' ~ icon %}
</li>
{% endfor %}

 

There are so many places (even including the Dawn theme codebase as well!) this could be useful to reduce drastically code complexity. In fact this is more readable than having a page long of cases.

auke
Shopify Partner
1 0 0

Hi @Dylan_Thacker-S,

Can you maybe explain why it is not possible to render snippets based on a variable name? The use case @flavioccf described earlier is exact the same as mine and in my opinion the workaround, which apparently relies on a bug, is a pretty clean way to render variabel snippets such as icons.

Any thoughts on a good way to render a snippet by a variable name, without having to write a case with all possible snippet names? (Like @flavioccf described)

Dixor
Shopify Partner
32 3 13

That why Shopify is a bad platform for developers.