Kermode

/ˈkɜːrmoʊd/
The Spirit Bear

Written by Gray Gilmore

I make websites for a living. I love CSS and building simple and modular stylesheets. Somewhere along the way I also turned into a Ruby developer. Life comes at you fast I guess. You can read my resume to learn about my journey so far.

You can find me as @graygilmore on several platforms:

Good ol' fashion email works, too: hello@kermode.co

You can subscribe to this blog via RSS: XML, JSON

Advanced Arrays in Shopify's Liquid

Liquid is Shopify’s templating language. It’s great and packed with useful helpers. Unfortunately, it struggles when it comes to creating arrays (probably fair, it’s a templating language, afterall).

Creating an array is a simple process, albeit not very intuitive:

{% assign myArray = "item-1|item-2|item-3" | split: "|" %}

We’re assigning a string to a new variable called myArray. The array is created when we use the split filter. Now we can run a for loop on our array:

{% for item in myArray %}
  {{ item }}
{% endfor %}

Will output:

item-1
item-2
item-3

Associative Arrays

Now things get a little complicated. Shopify has a great new feature for sorting collections. Instead of creating the dropdown manually, I wanted to create a simple for loop that looked like:

{% assign sortTitles = "Featured|$ Low to High|$ High to Low|A-Z|Z-A|Oldest to Newest|Newest to Oldest|Best Selling" | split: "|" %}

<select>
  {% for title in sortTitles %}
    <option value="{{ title | handle }}">{{ title }}</option>
  {% endfor %}
</select>

Unfortunately, {{ title | handle }} does not accurately correspond to the values we need to pass to the URL. I need to tie (or associate) the handle with a front-facing title that anyone could edit. Double array to the rescue!

{% assign sortHandles = "manual|price-ascending|price-descending|title-ascending|title-descending|created-ascending|created-descending|best-selling" | split: "|" %}
{% assign sortTitles = "Featured|$ Low to High|$ High to Low|A-Z|Z-A|Oldest to Newest|Newest to Oldest|Best Selling" | split: "|" %}

<select>
  {% for handle in sortHandles %}
    <option value="{{ handle }}">{{ sortTitles[forloop.index0] }}</option>
  {% endfor %}
</select>

We can use the current loop’s index value and use it to get our title from the sortTitles array. You just need to make sure that if you reorder any of the items in one array you do the same reordering in the other one.

The final markup, if you’re interested, looks like this:

{% for handle in sortHandles %}
  {% if collection.sort_by == blank and collection.default_sort_by == handle %}
    {% assign currentTitle = sortTitles[forloop.index0] %}
  {% elsif collection.sort_by == handle %}
    {% assign currentTitle = sortTitles[forloop.index0] %}
  {% endif %}
{% endfor %}

<label class="selected-text">Sort by: <strong>{{ currentTitle }}</strong></label>
<select>
  {% for handle in sortHandles %}
    {% if collection.sort_by == blank and collection.default_sort_by == handle %}
      <option value="{{handle}}" selected="selected">{{ sortTitles[forloop.index0] }}</option>
    {% elsif collection.sort_by == handle %}
      <option value="{{handle}}" selected="selected">{{ sortTitles[forloop.index0] }}</option>
    {% else %}
      <option value="{{handle}}">{{ sortTitles[forloop.index0] }}</option>
    {% endif %}
  {% endfor %}
</select>

There’s quite a bit of JavaScript involved as well, but we’ll save that for another post!