Recipes
Each recipe is a complete, tested example.
#Show something only if it is there
if alone is not enough, because "" and [] are truthy. Compare with blank:
Template
{% if settings.subtitle != blank %}<p class="subtitle">{{ settings.subtitle }}</p>{% endif %}Data
{"settings": {"subtitle": ""}}Output
#Fall back to a default
default treats nil, false, "" and empty collections as missing:
Template
<h2>{{ settings.heading | default: "Featured" }}</h2>Data
{"settings": {"heading": ""}}Output
<h2>Featured</h2>#Join a list with commas and "and"
Template
{% for name in settings.names %}{% if forloop.last and forloop.length > 1 %} and {% elsif forloop.index > 1 %}, {% endif %}{{ name }}{% endfor %}Data
{"settings": {"names": ["Ada", "Grace", "Hedy"]}}Output
Ada, Grace and Hedy#Plural words
Template
{{ settings.count }} {% if settings.count == 1 %}item{% else %}items{% endif %}Data
{"settings": {"count": 1}}Output
1 item#A grid with a fixed number of columns
forloop.index0 with modulo finds the first item of each row:
Template
{% for item in (1..5) %}{% assign column = forloop.index0 | modulo: 2 %}{% if column == 0 %}<div class="row">{% endif %}<span>{{ item }}</span>{% if column == 1 or forloop.last %}</div>{% endif %}{% endfor %}Output
<div class="row"><span>1</span><span>2</span></div><div class="row"><span>3</span><span>4</span></div><div class="row"><span>5</span></div>#The first few items, then "and more"
Template
{% for tag in settings.tags limit: 2 %}{{ tag }} {% endfor %}{% if settings.tags.size > 2 %}and {{ settings.tags.size | minus: 2 }} more{% endif %}Data
{"settings": {"tags": ["new", "sale", "tea", "gift"]}}Output
new sale and 2 more#Filter, sort and pick
Template
{% assign cheapest = settings.products | where: "available" | sort: "price" | first %}Cheapest available: {{ cheapest.title }}Data
{"settings": {"products": [
{"title": "Pot", "price": 30, "available": true},
{"title": "Cup", "price": 8, "available": false},
{"title": "Jug", "price": 12, "available": true}
]}}Output
Cheapest available: Jug#Put data in an attribute or a script
json is safe in both places:
Template
<div data-config="{{ settings.config | json }}"></div><script>const config = {{ settings.config | json }};</script>Data
{"settings": {"config": {"autoplay": true, "delay": 3}}}Output
<div data-config="{"autoplay":true,"delay":3}"></div><script>const config = {"autoplay":true,"delay":3};</script>#A short excerpt from rich text
Template
{{ settings.body | strip_html | truncatewords: 5 }}Data
{"settings": {"body": "<p>Our <b>first flush</b> Darjeeling has arrived this week.</p>"}}Output
Our first flush Darjeeling has...#Mark the current item
Template
{% for link in settings.links %}<a href="{{ link.url }}"{% if link.url == settings.current %} aria-current="page"{% endif %}>{{ link.title }}</a>{% endfor %}Data
{"settings": {"current": "/teas", "links": [{"title": "Home", "url": "/"}, {"title": "Teas", "url": "/teas"}]}}Output
<a href="/">Home</a><a href="/teas" aria-current="page">Teas</a>#Group items under headings
There is no group_by; sort by the group, then print a heading whenever it changes:
Template
{% assign last = nil %}{% for t in settings.teas | sort: "kind" %}{% if t.kind != last %}<h3>{{ t.kind }}</h3>{% assign last = t.kind %}{% endif %}<p>{{ t.name }}</p>{% endfor %}Data
{"settings": {"teas": [{"name": "Sencha", "kind": "green"}, {"name": "Assam", "kind": "black"}, {"name": "Matcha", "kind": "green"}]}}Error
expected "%}"A loop's collection cannot take filters directly. Assign the sorted list first:
Template
{% assign sorted = settings.teas | sort: "kind" %}{% assign last = nil %}{% for t in sorted %}{% if t.kind != last %}<h3>{{ t.kind }}</h3>{% assign last = t.kind %}{% endif %}<p>{{ t.name }}</p>{% endfor %}Data
{"settings": {"teas": [{"name": "Sencha", "kind": "green"}, {"name": "Assam", "kind": "black"}, {"name": "Matcha", "kind": "green"}]}}Output
<h3>black</h3><p>Assam</p><h3>green</h3><p>Sencha</p><p>Matcha</p>