Conditionals and Operators
Conditionals work similarly to most programming languages.
{% if age > 18 %}
You are an adult
{% elsif age > 12 %}
You are a teenager
{% else %}
You are a child
{% endif %}
Note the spelling of elsif
.
You can create boolean expressions using and
or or
, which are evaluated left to right:
{% if age < 50 or age > 50 %}
You're not 50
{% else %}
You must be 50
{% endif %}
There are no parentheticals allowed in Liquid. Any parenthetical logic needs to be created using nested conditionals.
If opposite of if
is unless
.
{% unless age > 17 %}
You are not an adult
{% endunless %}
Operators
Equality is a double ==
. Inequality is either !=
or <>
Other mathematical operators work as expected.
{% if age == 18 %}
{% if age <> 18 %}
{% if age != 18 %}
{% if age > 18 %}
{% if age < 18 %}
{% if age >= 18 %}
{% if age <= 18 %}
There is a contains
operator. It works differently for three different types of values:
- For a string it looks for the input string in the target string
- For a simple array it looks for an element value of the input in the target array
- For a dictionary it looks for the key of the input in the target dictionary
For any other type, it will return false
.
There are also startswith
and endswith
operators.
- For a string, it looks for the input string on either the start or end of the target string
- For a simple array, it looks for the input string as an element value on either the start or the end of the target array
Some examples:
{% if name startswith "D" %}
{% if children contains "Alec" %}
{% if days endswith "Sunday" %}
Operators are customizable.
All the operators are simply registered in the parser. For example.
RegisteredOperators["startswith"] = (a, b) => new StartsWithBinaryExpression(a, b);
RegisteredOperators["endswith"] = (a, b) => new EndsWithBinaryExpression(a, b);
RegisteredOperators["=="] = (a, b) => new EqualBinaryExpression(a, b);
RegisteredOperators["!="] = (a, b) => new NotEqualBinaryExpression(a, b);
RegisteredOperators["<>"] = (a, b) => new NotEqualBinaryExpression(a, b);
(Note the exact same class mapped to both !=
and <>
. I can’t see any reason why you couldn’t also map a single equals (=
) to EqualBinaryExpression
in the event your template developers can’t get used to the double equals syntax.)
We can write our own operators to create custom logic and behavior. For example, if we wanted to test whether a value is a direct multiple of another value, we could do this:
public class IsMultipleOfBinaryExpression : BinaryExpression
{
public IsMultipleOfBinaryExpression(Expression left, Expression right) : base(left, right) { }
public override async ValueTask<FluidValue> EvaluateAsync(TemplateContext context)
{
var leftValue = await Left.EvaluateAsync(context);
var rightValue = await Right.EvaluateAsync(context);
return BooleanValue.Create(leftValue.ToNumberValue() % rightValue.ToNumberValue() == 0);
}
}
Then we map it to an operator.
parser.RegisteredOperators["ismultipleof"] = (a,b) => new IsMultipleOfBinaryExpression(a, b);
Now we can use this syntax.
{% if age ismultipleof 10 %}
This is a milestone year for you!
{% endif %}
There is another example of this at the end of the chapter on checking for values.