Liquid Programming Annoyances (and Workarounds)

Cannot combine contains and other logical tests

Annoyance: This doesn’t work:

{% if arr1 contains var1 and var1 == var2 %}

Solution: You have to nest your conditionals — first check the contains, then make your other checks

{% if arr1 contains var1 %}
  {% if var1 == var2 %}
     <p>Var1 equals var2</p>
  {% endif %}
{% endif %}

Type Casting

Liquid is loosely typed, which usually makes things simple, if sometimes unpredictable.

Annoyance: you don’t need to declare a variable as a string or integer, but it will throw errors if you use the wrong type.

Solution: Convert a string to an integer by using a math filter and convert an integer to a string with a string filter.

{% assign var = 2 %}
{% assign string_var = integer | append: '' %}
{% assign integer_var = string_var | plus: 0 %}

Variable Scope in for loops

Annoyance: the loop variable assigned in the for statement is unavailable outside of the for loop, but all variables assigned within the loop are. Strange scoping.

Solution: assign it to a variable inside the loop, which is available outside of the loop.

Assume array ‘arr1’ has elements ‘one’, ‘two’, ‘three.’

{% for el in arr1 }
   {% assign copy = el %}
{% endfor %}
el = {{ el }}
copy  = {{ copy }}

Output:
el =
copy = three

In all the other languages I’ve worked with, el would be defined and would be the same as copy. Not in Liquid.

Of course, these are just the fixable “gotcha” type of issues. There are other things where it would be unfair to call it an issue. Arrays and objects are really intended to be mostly read-only in Liquid. So if you want to do multi-dimensional arrays in Liquid, you have to do some ugly gymnastics.

But to be fair, in that case you’re doing something that the language is actually designed to prevent. So that’s not a gotcha so much as attempting to do things the language is not really designed to do. It’s just a templating language, not a programming language.

Leave a Comment