Liquid Tutorial 10 - Truthiness in Logic: using Liquid to determine if a field is empty or blank
Improve the accuracy of your if statements by using the blank keyword to catch a range of falsy states.
Written By Luke Wakefield
Last updated About 1 month ago
Often we will use if statements to hide sections of HTML if the data which would normally populate them does not exist. E.g. rather than show a broken missing image, we might skip an image tag.
Truthiness and Falsiness
If statements have a concept of truthiness, which they use to measure whether a condition passes or not. Yes, these are technical terms made up by computer programmers!
The false keyword is falsy, that makes sense by definition, but consider how that works in an if statement:
Example{% if false %}
Condition passed
{% else %}
Condition failed
{% endif %}The outcome might be slightly counter intuitive, but it exposes how if statements really work. A long condition is resolved, and either it is true and the the condition passes, or it is false and condition fails.
Example{% if 2 == 4 %}
Condition passes
{% else %}
Condition fails
{% endif %}2 == 4 is false, as is the keyword false. Simply writing false is a shortcut to the condition failing.
Which data values are truthy and falsy in Liquid?
All values in Liquid are truthy except nil and false. As explained in Liquid Tutorial 2 - Liquid variables and types if a variable contains nil, it is as if the variable never existed at all. Therefore if you are checking for variables or properties which don’t exist, they will be nil and therefore falsy.
Handling non-existent variables
Thinking about nil variables which don’t exist. For example, let’s look at how to tell if a Page is a homepage or not; this data can be accessed in the context object on any page:
Example{{context.page.metadata.is_homepage}}Whether a page is the homepage or not is determined by the is_homepage variable: is_homepage which has the value true if you are indeed on the homepage. However if a Page is not the homepage, rather than is_homepage being set to false, the is_homepage variable doesn't exist.
Say we wanted to run some code on every Page that isn't the homepage, we might write something like this:
Example{% if context.page.metadata.is_homepage == false %} <!-- output content --> {% else %} <!-- output homepage content --> {% endif %}
This would work fine if we were on the Homepage, as the variable's value would be true. However, on other Pages, it would not behave as expected, as is_homepage would be undefined..
Now lets look at the Liquid keyword blank. This refers to having a value of either: Empty, Null or False.
If I now check "is_homepage" like so:
Example{% if context.page.metadata.is_homepage == blank %} {% comment %}output content.{% endcomment %} {% else %} {% comment %}output homepage content.{% endcomment %} {% endif %}
This will now work whether is_homepage is set to false or whether it does not exist at all!
Thinking about edge cases in truthiness / falsiness
To avoid bugs in your Liquid code, you need to consider edge cases: “What if the variable I am using has a value which is not treated as truthy or falsy as I expect? What value could cause that problem?”
Let’s look at another example. This time we have an object with some properties. We only want to display the properties on the page if they exist:
Example{% parse_json product %}
{
"type": "car",
"make": "Ford",
"model": "Prefect",
"image": "images/ford_prefect.jpg",
"inventory": 0,
"2nd hand": false,
"notes": ""
}
{% endparse_json %}
{% if product.type %}
<p>The product is a {{ product.type }}.</p>
{% endif %}
{% if product.make %}
<p>The product is made by {{ product.make }}.</p>
{% endif %}
{% if product.model %}
<p>The product is a {{ product.model }}.</p>
{% endif %}
{% if product.image %}
<p>The product has an image of {{ product.image }}.</p>
{% endif %}
{% if product.inventory %}
<p>The product has an inventory of {{ product.inventory }}.</p>
{% else %}
<p>The product is out of stock</p>
{% endif %}
{% if product["2nd hand"] %}
<p>The product is a 2nd hand product.</p>
{% endif %}
{% if product.notes %}
<p>The product has the following notes: {{ product.notes }}.</p>
{% endif %}Checking the HTML notes, this is mostly right, except for two issues:
The inventory 0 is seen as truthy, because it is a number. To show the out of stock message we need to add an
andstatement to rule out 0.We don’t want to display the notes if they are an empty string containing no characters. An empty String is still a String as far as Liquid is concerned and is truthy. We will need to use the blank keyword, which includes empty String in order to make the condition fail when it receives empty string.
In some languages, like JavaScript, 0 can be considered falsy. In Liquid, it is truthy.
Example{% parse_json product %}
{
"type": "car",
"make": "Ford",
"model": "Prefect",
"image": "images/ford_prefect.jpg",
"inventory": 0,
"2nd hand": false,
"notes": ""
}
{% endparse_json %}
{% if product.type %}
<p>The product is a {{ product.type }}.</p>
{% endif %}
{% if product.make %}
<p>The product is made by {{ product.make }}.</p>
{% endif %}
{% if product.model %}
<p>The product is a {{ product.model }}.</p>
{% endif %}
{% if product.image %}
<p>The product has an image of {{ product.image }}.</p>
{% endif %}
{% if product.inventory and product.inventory != 0 %}
<p>The product has an inventory of {{ product.inventory }}.</p>
{% else %}
<p>The product is out of stock</p>
{% endif %}
{% if product["2nd hand"] %}
<p>The product is a 2nd hand product.</p>
{% endif %}
{% if product.notes != blank %}
<p>The product has the following notes: {{ product.notes }}.</p>
{% endif %}