Liquid Tag Reference

From Spiffy Stores Knowledge Base

Liquid Tags provide the logic and control flow in your template. They allow you to display data conditionally and to dynamically change the way the template is rendered according to the data in the Liquid variables.

Comments

A comment is the simplest of tags. It just swallows content.

Hi fred {% comment %} you stink {% endcomment %}

Variable Assignment

You can store data in your own variables, to be used in output or other tags as desired.

The simplest way to create a variable is with the assign tag, which has a pretty straightforward syntax:

{% assign name = 'freestyle' %}
{% for t in collections.tags %}{% if t == name %}
  <p>Freestyle!</p>
{% endif %}{% endfor %}

Another way of doing this would be to assign true/false values to the variable:

{% assign freestyle = false %}
{% for t in collections.tags %}{% if t == 'freestyle' %}
  {% assign freestyle = true %}
{% endif %}{% endfor %}
{% if freestyle %}
  <p>Freestyle!</p>
{% endif %}

If you want to combine a number of strings into a single string and save it to a variable, you can do that with the capture tag. This tag is a block which "captures" whatever is rendered inside it and assigns it to the given variable instead of rendering it to the screen. Here's how it works:

  {% capture attribute_name %}{{ item.title }}-{{ i }}-color{% endcapture %}

  <label for="{{ attribute_name }}">Colour:</label>
  <select name="attributes[{{ attribute_name }}]" id="{{ attribute_name }}">
    <option value="red">Red</option>
    <option value="green">Green</option>
    <option value="blue">Blue</option>
  </select>

Arrays

If a liquid expression returns an array of objects, then you can access the members of the array using an index notation.

For example to access the third element of an array of products

{{ collection.products[2].title }}

All array elements are accessed using a zero-based index, so the first element of the array is always index 0.

Additionally, three special methods are available for arrays.

'size' - Returns the number of elements in the array
'first' - Returns the first element in the array
'last' - Returns the last element in the array
{{ collection.products.first }}
{{ collection.products.last }}
You have {{ cart.items.size }} items in your cart

Raw Tags

If you need to include code in your template that you don't want interpreted by the Liquid parser, then you need to enclose it with raw tags.

These tags will allow you to incorporate code such as JavaScript templates that use the same curly braces as Liquid.

{% raw %}{{ 3 | plus: 4}}{% endraw %} is usually equal to 7.

The code between the raw tags is protected, so the result is

{{ 3 | plus: 4}} is usually equal to 7.

If / Else

The conditional expressions formed with if/else should be a familiar construction from most programming languages. Liquid allows you to write simple expressions in the if.

The conditions that can be used to test for logical conditions are:

'==' - Equal
'!=' - Not Equal
'<>' - Not Equal
'<' - Less Than
'>' - Greater Than
'>=' - Greater Than or Equal
'<=' - Less Than or Equal
'contains' - String contains substring

Compound expressions may be formed by the use of or and and expressions.

{% if user %}
  Hi {{ user.name }}
{% endif %}

{% if user.name == 'fred' %}
  hi fred
{% endif %}

{% if user.name != 'fred' %}
  you aren't fred
{% endif %}

{% if user.name == 'fred' or user.name == 'dirk' %}
  hi dirk or fred
{% endif %}

{% if user.name == 'fred' and user.last_name == 'bloggs' %}
  hi fred bloggs
{% endif %}

{% if user.creditcard == null %}
  user has no credit
{% endif %}

{% if user.payments == empty %}
  you never paid !
{% endif %}

{% if user.age > 18 %}
  Login here
{% else %}
  Sorry, you are too young
{% endif %}

{% if user.name contains 'y' %}
  Sorry, we don't allow users with a 'y' in their name!  
{% endif %}

Unless / Else

The conditional expressions formed with Unless/Else are the reverse of the usual If/Else logic. An Unless/Else block is written using exactly the same expressions and conditions as an If/Else block, but the test logic is reversed.

{% unless user.name == 'fred' %}
  you aren't fred
{% endunless %}

{% unless user.age > 18 %}
  Sorry, you are too young
{% else %}
  Login here
{% endunless %}

IfChanged Block

The ifchanged block tag is used within a loop. It checks its own rendered contents against its previous state and only displays its content if the value has changed.

For example, in order to show the date only when a post is published on a new day (always displaying the time):

{% ifchanged %}
  <div class="date">{{ article.published_at | date: '%B %d'  }}</div>
{% endifchanged %}
<div class="time">{{ article.published_at | date: '%I:%M %p'  }}</div>

Case Statement

If you need more than one condition you can use the Case statement

{% case line_item.quantity %}
  {% when 0 %}
  none
  {% when 1 %}
  one
  {% when 2 %}
  two
  {% else %}
  a few more...
{% endcase %}

Example:

{% case template %}
	
{% when 'label' %}
     // {{ label.title }}
{% when 'product' %}
     // {{ product.vendor | link_to_vendor }} / {{ product.title }}
{% else %}
     // {{page_title}
{% endcase %}

Cycle

Often you have to cycle through an number of alternative values. Liquid has built-in support for such operations using the Cycle tag.

{% cycle 'one', 'two', 'three' %}
{% cycle 'one', 'two', 'three' %}
{% cycle 'one', 'two', 'three' %}
{% cycle 'one', 'two', 'three' %}

...will result in...

one
two
three
one

If no name is supplied for the cycle group then its assumed that multiple calls with the same parameters are one group.

If you want to have total control over cycle groups you can optionally specify the name of the group. This can even be a variable.

{% cycle 'group 1': 'one', 'two', 'three' %}
{% cycle 'group 1': 'one', 'two', 'three' %}
{% cycle 'group 2': 'one', 'two', 'three' %}
{% cycle 'group 2': 'one', 'two', 'three' %}

...will result in...

one
two
one
two

For Loops

Liquid allows for loops over collections. This allows you to loop over things like line-items in an order.

  {% for item in order.line-items %}
    {{ item.description }}
  {% endfor %}

The order of the loop may be reversed by adding the flag reversed.

  {% for item in order.line-items reversed %}
    {{ item.description }}
  {% endfor %}

During every For loop, the following helper variables are available for additional control over the results.

 forloop.length     # => length of the entire for loop
 forloop.index      # => index of the current iteration
 forloop.index0     # => index of the current iteration (zero based)
 forloop.rindex     # => how many items are still left?
 forloop.rindex0    # => how many items are still left? (zero based)
 forloop.odd        # => is this iteration odd (zero based)?
 forloop.even       # => is this iteration even (zero based)?
 forloop.first      # => is this the first iteration?
 forloop.last       # => is this the last iteration?

There are several attributes you can use to influence which items you receive in your loop

  • limit lets you restrict how many items you get
  • offset lets you start the collection with the nth item.
  # array = [1,2,3,4,5,6]
  {% for item in array limit:2 offset:2 %}
    {{ item }}
  {% endfor %}
  # results in 3,4

Instead of looping over an existing collection, you can define a range of numbers to loop through. The range can be defined by both literal and variable numbers:

  # if item.quantity is 4...
  {% for i in (1..item.quantity) %}
    {{ i }}
  {% endfor %}
  # results in 1,2,3,4

Tables

Liquid can also create table rows and cells for you, although you still need to wrap a table tag around the tablerow tag.

  <table>
    {% tablerow item in items cols: 3 limit: 12 %}
      {{ item.variable }}
    {% endtablerow %}
  </table>

You can also find out whether a table cell is the first or last column in a row or directly query the column number.

 tablerowloop.length       # => length of the entire for loop
 tablerowloop.index        # => index of the current iteration
 tablerowloop.index0       # => index of the current iteration (zero based)
 tablerowloop.rindex       # => how many items are still left?
 tablerowloop.rindex0      # => how many items are still left? (zero based)
 tablerowloop.first        # => is this the first iteration?
 tablerowloop.last         # => is this the last iteration?
 tablerowloop.odd          # => is this iteration odd (zero based)?
 tablerowloop.even         # => is this iteration even (zero based)?
 tablerowloop.col          # => index of column in the current row
 tablerowloop.col0         # => index of column in the current row (zero based)
 tablerowloop.col_first    # => is this the first column in the row?
 tablerowloop.col_last     # => is this the last column in the row?
  {% tablerow item in items cols: 3 %}
    {% if col_first %}
      First column: {{ item.variable }}
    {% else %}
      Different column: {{ item.variable }}
    {% endif %}
  {% endtablerow %}

Including Snippets

Liquid code can include code fragments or snippets from the theme's snippets folder or from the global snippets library. The theme's snippets folder is searched first before a search is made of the global library. This means that you can use any of the snippets from the global library, but override the snippet by creating a snippet of the same name in the theme's snippet folder.

Details of all the global snippets can be found here: Using global Liquid snippets.

These snippets can be used to include code in a layout, template or another snippet.

All snippets are named as follows

_snippet_name.liquid

A snippet is included into Liquid code by using the include tag.

{% include 'snippet_name' %}

Note that the leading '_' character is not required on the include tag.

When a snippet is included into another piece of Liquid code, it will be rendered using all of the currently assigned variables. An optional with parameter allows you to assign a value to a variable bound to the snippet's name within the snippet's context.

For example, assume we have a snippet called _widget.liquid.

<p>The widget shape is {{ widget }}. It is {{ colour }}.</p>

Within a template we can include the following code:

{% assign colour = 'yellow' %}
{% include 'widget' %}
{% include 'widget' with 'round' %}
{% include 'widget' with 'square' %}
{% assign colour = 'green' %}
{% include 'widget' with 'triangle' %}

This will render as

<p>The widget shape is . It is yellow.</p>
<p>The widget shape is round. It is yellow.</p>
<p>The widget shape is square. It is yellow.</p>
<p>The widget shape is triangle. It is green.</p>

Further Reference