Liquid: How to assign the output of an operator to a variable? - operators

I'm working with Liquid templates for Shopify. I want some elements to show up only if the month happens to be December. Since there are multiple elements that need this, I want to set a variable at the top of the document and refer to it later. Here's what I've got that's working:
<!-- At the top of the page -->
{% assign month = 'now' | date: "%m" %}
{% if month == "12" %}
{% assign isDecember = true %}
{% else %}
{% assign isDecember = false %}
{% endif %}
<!-- Only show in December -->
{% if isDecember %}
Happy Holidays
{% endif %}
This works (for testing I change "12" to the current month) but it is pretty ugly. In most languages I would do something like this:
{% assign isDecember = (month == "12") %}
Liquid doesn't accept parentheses, so obviously this won't work. And it doesn't work without parentheses either. The documentation has examples for using operators and for assigning static values to variables, but nothing about combining the two.
I can assign the output of a | filter to a variable, but there don't seem to be filters to cover every operator (or even the necessary "=="), so that's unsatisfactory.
Is there any way to assign the output of an operator to a variable in Liquid?

There isn't a way to do that elegantly and according to this, they won't support ternary operators. There's a mention of someone trying a similar thing.
A slightly shorter/different version would be:
{% assign month = 'now' | date: "%m" %}
{% liquid
case month
when '12'
assign isDecember = true
else
assign isDecember = false
endcase %}

You could altogether avoid using an intermediary boolean flag variable isDecember as Liquid assign with only boolean variables seems to not working within if/endif. Here are the solutions.
Just use plain strings:
{% assign month = 'now' | date: "%m" %}
{% if month == "12" %}
Happy Holidays
{% endif %}
Or use plain string assignments (not boolean values assignments) within ifs:
{% if month == "12" %}
{% assign phrase = "Happy Holidays" %}
{% else %}
{% assign phrase = "Happy usual time of the year" %}
{% endif %}
Now my message to you is: {{ phrase }}
Still want unsing intermediary isDecember? If you would put some dummy text assignment within either clause of if/else that would work too.
{% if month == "12" %}
{% assign dummy = "summy" %}
{% assign isDecember = true %}
{% else %}
{% assign isDecember = false %}
{% endif %}
Hope that helps.

Related

Django template syntax error: could not parse remainder % 2

I am getting a TemplateSyntaxError: "could not parse remainder % 2 from num%2":
{% if num%2 ==0 %}
{{"Even"}}
{% else %}
{{"Odd"}}
{% endif %}
You can't use arbitrary Python expressions in Django templates. You should create a custom filter for them.
However, for your expression there is a built-in tag divisibleby. From its example:
{{ value|divisibleby:"2" }}
If value is 4, the output would be True. So the final answer looks like (untested):
{% if num|divisibleby:"2" %}
Even
{% else %}
Odd
{% endif %}

How to use a variable as a key in a hash in liquid (Shopify)

I would like to set up a hash variable using strings from an array dynamically (instead of writing 1000 lines of code).
As well I would like to use a dynamically created string to access a hash by using it as the key - for a built-in (what I assume is a hash) object - settings. Settings allow you to access data in settings_schema.json, eg: settings.my_custom_setting
According to this documentation: https://github.com/Shopify/liquid/wiki/Liquid-for-Designers
"For hashes, the key must be a literal quoted string or an expression that resolves to a string."
so I have tried {% assign filter[thisFilter] = false %} but get an error: ParseError: illegal token
First issue / accessing hash key with a variable:
{% comment %} All possible filters {% endcomment %}
{% assign allFilters = "color,size,collection,style,height,function,artist" %}
{% assign allFiltersArray = allFilters | split ',' %}
{% comment %} hash of filters each set to false {% endcomment %}
{% for thisFilter in allFiltersArray %}
{% assign filter[thisFilter] = false %}
{% endfor %}
Second issue, accessing settings object with a dynamically generated key:
{% comment %} set to true whichever filters are configured in settings for this collection {% endcomment %}
{% for thisCollection in allCollectionsArray %}
{% if thisCollection == currentCollection %}
{% for thisFilter in allFiltersArray %}
{% assign itemToCheck = "filter_" | append: thisCollection | append: "_" | append: thisFilter %}
{% if settings[itemToCheck] %}
{% assign filter[thisFilter] = true %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
In the first issue, I expect the result to be a hash such as:
filter['color'] = false (or filter.color = false)?
filter['size'] = false
In the second issue, I'm expecting something like:
{% if settings.filter_shirts_color %}
What you are trying to do is not possible. If you read further on your provided link Liquid for Designers, it is mentioned
Note that there is no way to write a literal array or hash as an
expression; arrays and hashes must be passed into the template, or
constructed obliquely with a tag or output statement.
Moreover, even if you have such hash, you cannot assign it new value. For example,
{% assign settings['some-setting-id'] = false %}
This will not work. Same is the case with array created using split filter. You cannot assign new values on any index.
For the second issue, this should work, the error in your case most probably is because of invalid generated string or there is no setting with that id. This should work fine and display value for that setting.
{%assign string_key = 'setting-key'%}
{{settings[string_key]}}
But this will not work because
{%assign string_key = 'setting-key'%}
{{settings.string_key}}
my_hash.key — Hashes also allow a shorter "dot" notation, where the
name of the variable is followed by a period and the name of a key.
This only works with keys that don't contain spaces, and (unlike the
square bracket notation) does not allow the use of a key name stored
in a variable.

specify variable array index for liquid

My liquid code is
{% assign _product_id = product.id %}
{% assign _product_tag = product.collections[0].title}
{% assign _product_name = product.title %}
{{_product_tag}}
{% assign pagla_array = collections[_product_tag].products %}
{{ pagla_array.first.title }}
Here last line showing nothing. if I use a static index for assigning pagla_array like {% assign pagla_array = collections['Beans'].products %} then it show value. What wrong did I make here?
This line:
{% assign _product_tag = product.collections[0].title}
Is not closed correctly. It should end with %}
In addition you should use handles for the collections, not title.
So it should become:
{% assign _product_tag = product.collections[0].handle %}
....
{% assign pagla_array = collections[_product_tag].products %}

can i use OR in Shopify case

let say I have three products and made a case
I want to know if I can use OR instead of duplicating the content again
{% case shipping_method.title %}
{% when 'packageA' || 'packageB' %}
around 5000 lines
{% when 'packageC' %}
{% endcase %}
Yes you can but it must be a valid syntax. || is not a valid operator in liquid.
You have to use or instead so it becomes {% when 'packageA' or 'packageB' %}

Liquid - Convert Array to Lowercase

I'm using Shopify and want to hook into customer tags, however they are case sensitive. So {% if customer.tags contains "wholesale" %} is not the same as {% if customer.tags contains "Wholesale" %}. My client may or may not stick to one case when applying tags so I want to guard against that in the future.
I would like to take an array, customer.tags, and convert all of the values to lowercase. I'm trying to work out the logic but am having trouble.
I want to put customer.tags into a new array which isn't working.
{% assign newArray = customer.tags %}
{{ newArray }}
What am I doing wrong?
You could use the downcase filter for this:
{% assign contains_wholesale = false %}
{% for tag in customer.tags %}
{% assign lowercase_tag = tag | downcase %}
{% if lowercase_tag == 'wholesale' %}
{% assign contains_wholesale = true %}
{% endif %}
{% endfor %}
Note: downcase just works for ASCII characters. If you need to search for strings with accented letters or other Unicode characters then this won't be enough.
if you would like to keep customer.tags as an array so you can keep using contains in a simple if statement (like your example). You could also chain a couple of liquid filters together to turn all of the strings within the array to lowercase.
Example:
{% assign lowercaseTags = customer.tags | join: ',' | downcase | split: ',' %}
{% assign randomString = 'WholeSale' | downcase %}
{% if lowerCaseTags contains randomString %}
{% comment %}
Will now match regardless of case sensitivity
{% endcomment %}
{% endif %
Explanation:
Join filter: Turn the array into a string seperated by ,
Downcase filter: make the whole string lowercase
Split filter: opposite of join, recreates the array from the string based on the character used in join ,
Another solution as you use the "contains" operator would be to skip the "w".
Something like {% if customer.tags contains 'holesale' %} should work.