Twig Conditionals
Complete guide to conditional statements in Total CMS Twig templates for controlling template flow based on dynamic data.
Overview
Section titled “Overview”Conditional statements allow you to control the flow of your templates based on dynamic data. In Twig, you can use the {% if %} tag to test conditions and display content accordingly.
Basic syntax:
{% if condition %} Content to display if true{% endif %}With else:
{% if condition %} Content when true{% else %} Content when false{% endif %}With elseif:
{% if condition1 %} Content for condition 1{% elseif condition2 %} Content for condition 2{% else %} Default content{% endif %}Basic Comparisons
Section titled “Basic Comparisons”Has Value (Truthy Test)
Section titled “Has Value (Truthy Test)”Tests if a variable has a “truthy” value. For booleans, it checks true/false. For variables, it returns false if undefined, null, empty string, empty array, or the number 0.
{% if post.draft %} This post is a draft{% endif %}Not (Negation)
Section titled “Not (Negation)”Inverts the condition - returns true when the value is false or falsy.
{% if not post.featured %} This post is not featured{% endif %}String Equality
Section titled “String Equality”Checks if a string value exactly matches another string.
{% if page.name == "home" %} Welcome to the home page{% endif %}Boolean Comparison
Section titled “Boolean Comparison”Explicitly compares a boolean value. Can use == true or == false.
{% if blog.featured == true %} This is a featured post{% endif %}Numeric Comparisons
Section titled “Numeric Comparisons”Compare numbers using operators: >, <, >=, <=, ==, !=
{% if product.inventory >= 10 %} In stock{% elseif product.inventory > 0 %} Low stock{% else %} Out of stock{% endif %}Not Equal
Section titled “Not Equal”Checks if values are not equal using != operator.
{% if user.role != "guest" %} Welcome back, member!{% endif %}Existence & Type Checks
Section titled “Existence & Type Checks”Variable Defined
Section titled “Variable Defined”Check if a variable has been defined in the template context.
{% if myobject is defined %} Object exists{% endif %}
{% if myobject is not defined %} Object does not exist{% endif %}Null Check
Section titled “Null Check”Check if a variable is null (explicitly set to null, not just undefined).
{% if user.avatar is null %} <img src="default-avatar.png">{% else %} <img src="{{ user.avatar }}">{% endif %}Empty Check
Section titled “Empty Check”Tests if a variable is empty (empty string, empty array, or false).
{% if object.tags is empty %} No tags available{% else %} {% for tag in object.tags %} {{ tag }} {% endfor %}{% endif %}File Exists
Section titled “File Exists”Check if a file exists in your Total CMS file system.
{% if fileExists('documents/report.pdf') %} <a href="documents/report.pdf">Download Report</a>{% endif %}Image Exists
Section titled “Image Exists”Check if an image property exists for an object before attempting to display it.
{% if imageExists(post.image) %} {{ cms.render.image(post.id, {collection: 'blog', property: 'image'}) }}{% else %} <img src="placeholder.jpg">{% endif %}Combining Conditions
Section titled “Combining Conditions”OR - Either Condition
Section titled “OR - Either Condition”Returns true if either condition is true. You can chain multiple OR conditions.
{% if user.role == "editor" or user.role == "admin" %} You have editing permissions{% endif %}AND - Both Conditions
Section titled “AND - Both Conditions”Returns true only if all conditions are true. You can chain multiple AND conditions.
{% if post.published == true and post.date < "now"|date %} This post is live{% endif %}Complex Combinations
Section titled “Complex Combinations”Use parentheses to group conditions and control evaluation order.
{% if (user.role == "admin" or user.role == "editor") and post.draft == false %} Show edit button{% endif %}Array & Collection Tests
Section titled “Array & Collection Tests”Value in Array
Section titled “Value in Array”Check if a value exists within an array of values.
{% if post.category in ["news", "updates", "announcements"] %} This is a news-related post{% endif %}Array Contains Value (Reverse)
Section titled “Array Contains Value (Reverse)”Check if an array variable contains a specific value.
{% if "admin" in user.groups %} Administrator access granted{% endif %}Array Length
Section titled “Array Length”Check the number of items in an array using the length filter.
{% if post.tags|length > 0 %} Tags: {{ post.tags|join(', ') }}{% endif %}
{% if gallery.images|length >= 10 %} This gallery has {{ gallery.images|length }} images{% endif %}Collection Has Objects
Section titled “Collection Has Objects”Check if a collection has any objects before looping.
{% set posts = cms.collection.objects('blog') %}{% if posts|length > 0 %} {% for post in posts %} {{ post.title }} {% endfor %}{% else %} No blog posts found{% endif %}Iterable Test
Section titled “Iterable Test”Check if a variable can be iterated over (arrays, objects, etc.).
{% if items is iterable %} {% for item in items %} {{ item }} {% endfor %}{% endif %}String Operations
Section titled “String Operations”Starts With
Section titled “Starts With”Check if a string begins with a specific substring.
{% if product.sku starts with "PROD-" %} Standard product{% endif %}Ends With
Section titled “Ends With”Check if a string ends with a specific substring.
{% if user.email ends with "@example.com" %} Internal user account{% endif %}Contains (Using ‘in’)
Section titled “Contains (Using ‘in’)”Check if a string contains a substring. Use |lower for case-insensitive matching.
{% if "urgent" in post.title|lower %} <span class="badge urgent">Urgent</span>{% endif %}Regular Expression Match
Section titled “Regular Expression Match”Test if a string matches a regular expression pattern. Use double backslashes for escape sequences.
{% if user.phone matches '/^[\\d\\.\\-\\(\\)\\s]+$/' %} Valid phone format{% endif %}
{% if post.title matches '/\\d{4}/' %} Title contains a year{% endif %}Date & Time Comparisons
Section titled “Date & Time Comparisons”Date Before Now
Section titled “Date Before Now”Compare a date field to the current date/time.
{% if event.date < "now"|date %} This event has passed{% endif %}Date After Specific Date
Section titled “Date After Specific Date”Compare a date to a specific date string.
{% if post.date > "2024-01-01"|date %} Posted this year{% endif %}Date Range
Section titled “Date Range”Check if a date falls within a specific range. Use modifiers like +7 days, -1 month, etc.
{% if event.date >= "now"|date and event.date <= "+7 days"|date %} Happening this week{% endif %}Date Between Two Dates
Section titled “Date Between Two Dates”Store dates in variables for cleaner comparisons.
{% set startDate = "2024-06-01"|date %}{% set endDate = "2024-08-31"|date %}{% if event.date >= startDate and event.date <= endDate %} Summer event{% endif %}Total CMS Specific Tests
Section titled “Total CMS Specific Tests”Object Exists
Section titled “Object Exists”Check if an object exists before using it.
{% set page = cms.collection.object('pages', 'about') %}{% if page %} {{ page.content }}{% else %} Page not found{% endif %}Toggle State
Section titled “Toggle State”Check a toggle’s state from your Total CMS settings.
{% if cms.toggle('maintenance-mode') %} <div class="alert">Site under maintenance</div>{% endif %}Config Value
Section titled “Config Value”Access and test configuration values.
{% if cms.config('debug') == true %} Debug mode is enabled{% endif %}Environment Check
Section titled “Environment Check”Check which environment the site is running in.
{% if cms.env == 'development' %} <div class="debug-bar">Development Mode</div>{% endif %}User Authentication
Section titled “User Authentication”Check if a user is logged in.
{% if cms.user %} Welcome back, {{ cms.user.name }}!{% else %} <a href="/login">Login</a>{% endif %}User Permission
Section titled “User Permission”Check if the logged-in user has specific roles or permissions.
{% if cms.user and "editor" in cms.user.roles %} <a href="/admin/edit">Edit Content</a>{% endif %}Advanced Tests
Section titled “Advanced Tests”Default Values
Section titled “Default Values”Provide a default value if the variable is undefined or empty.
{% if product.rating|default(0) >= 4 %} Highly rated!{% endif %}Even/Odd Tests
Section titled “Even/Odd Tests”Test if a number is even or odd. Useful for alternating row styles.
{% for post in posts %} <div class="{% if loop.index is even %}even{% else %}odd{% endif %}"> {{ post.title }} </div>{% endfor %}Divisible By
Section titled “Divisible By”Check if a number is divisible by another number. Great for grid layouts.
{% for item in items %} {{ item.name }} {% if loop.index is divisible by(3) %} </div><div class="row"> {% endif %}{% endfor %}Same As
Section titled “Same As”Check if two variables reference the exact same object (identity check, not equality).
{% if currentPage is same as(homePage) %} <span class="active">Home</span>{% endif %}Constant Check
Section titled “Constant Check”Check if a value matches a defined constant.
{% if status is constant('STATUS_ACTIVE') %} Active status{% endif %}Ternary Operator
Section titled “Ternary Operator”Inline conditional using the ternary operator condition ? true : false.
{{ post.featured ? 'Featured Post' : 'Regular Post' }}
{% set cssClass = post.published ? 'published' : 'draft' %}<div class="{{ cssClass }}">{{ post.title }}</div>Null Coalescing
Section titled “Null Coalescing”Return the first defined value using the ?? operator. Similar to multiple |default filters.
{{ user.nickname ?? user.name ?? 'Guest' }}
{% set displayName = user.preferredName ?? user.firstName ?? user.username %}Loop-Specific Conditionals
Section titled “Loop-Specific Conditionals”First Item
Section titled “First Item”Check if current iteration is the first item in the loop.
{% for post in posts %} {% if loop.first %} <div class="featured">{{ post.title }}</div> {% else %} <div class="regular">{{ post.title }}</div> {% endif %}{% endfor %}Last Item
Section titled “Last Item”Check if current iteration is the last item (useful for adding separators).
{% for item in items %} {{ item.name }}{% if not loop.last %}, {% endif %}{% endfor %}Loop Index
Section titled “Loop Index”Use loop.index (1-based) or loop.index0 (0-based) to check position.
{% for post in posts %} {% if loop.index <= 3 %} <div class="top-post">{{ post.title }}</div> {% endif %}{% endfor %}Loop Length
Section titled “Loop Length”Access the total number of items being looped through.
{% for post in posts %} Post {{ loop.index }} of {{ loop.length }}{% endfor %}Best Practices
Section titled “Best Practices”Always Check Object Existence
Section titled “Always Check Object Existence”Always check if objects exist before accessing their properties to avoid errors:
{% set post = cms.collection.object('blog', 'my-post') %}{% if post %} {{ post.title }}{% endif %}Use Variables for Complex Conditions
Section titled “Use Variables for Complex Conditions”Make complex conditions more readable by using variables:
{% set isAdmin = cms.user and "admin" in cms.user.roles %}{% set isPublished = post.published and post.date <= "now"|date %}
{% if isAdmin or isPublished %} {{ post.content }}{% endif %}Combine Existence and Value Checks
Section titled “Combine Existence and Value Checks”For safety, combine existence and value checks:
{% if post.gallery is defined and post.gallery is not empty %} {{ cms.render.gallery(post.id) }}{% endif %}Performance Considerations
Section titled “Performance Considerations”Avoid calling CMS functions multiple times in conditions:
{# Bad - calls function multiple times #}{% if cms.collection.objects('blog')|length > 0 %} {{ cms.collection.objects('blog')|length }} posts{% endif %}
{# Good - calls function once #}{% set posts = cms.collection.objects('blog') %}{% if posts|length > 0 %} {{ posts|length }} posts{% endif %}Safe Image/File Access
Section titled “Safe Image/File Access”Always check existence before accessing files or images:
{# Check if image exists #}{% if imageExists(post.image) %} {{ cms.render.image(post.id, {property: 'hero'}) }}{% endif %}
{# Check if file exists #}{% if fileExists('downloads/brochure.pdf') %} <a href="downloads/brochure.pdf">Download</a>{% endif %}Quick Reference
Section titled “Quick Reference”Comparison Operators
Section titled “Comparison Operators”| Operator | Description | Example |
|---|---|---|
== | Equal to | price == 10 |
!= | Not equal to | status != "draft" |
< | Less than | age < 18 |
> | Greater than | count > 5 |
<= | Less than or equal | score <= 100 |
>= | Greater than or equal | rating >= 4 |
Logical Operators
Section titled “Logical Operators”| Operator | Description | Example |
|---|---|---|
and | Both conditions true | published and featured |
or | Either condition true | admin or editor |
not | Negate condition | not deleted |
() | Group conditions | (a or b) and c |
| Test | Description | Example |
|---|---|---|
defined | Variable exists | var is defined |
null | Value is null | value is null |
empty | Value is empty | array is empty |
even | Number is even | num is even |
odd | Number is odd | num is odd |
iterable | Can be looped | items is iterable |
divisible by | Divisible by number | num is divisible by(3) |
same as | Same object | a is same as(b) |
constant | Matches constant | x is constant('Y') |
String Tests
Section titled “String Tests”| Test | Description | Example |
|---|---|---|
starts with | String starts with | str starts with "hello" |
ends with | String ends with | str ends with ".com" |
matches | Matches regex | str matches '/\\d+/' |
in | Contains substring | "test" in str |
Loop Variables
Section titled “Loop Variables”| Variable | Description | Example |
|---|---|---|
loop.index | Current iteration (1-based) | {{ loop.index }} |
loop.index0 | Current iteration (0-based) | {{ loop.index0 }} |
loop.first | True if first iteration | {% if loop.first %} |
loop.last | True if last iteration | {% if loop.last %} |
loop.length | Total items in loop | {{ loop.length }} |
loop.parent | Parent loop context | {{ loop.parent.index }} |
Common Patterns
Section titled “Common Patterns”Safe Navigation
Section titled “Safe Navigation”{# Check nested properties safely #}{% if user is defined and user.profile is defined and user.profile.avatar %} {{ user.profile.avatar }}{% endif %}
{# Or use default values #}{{ user.profile.avatar|default('default.jpg') }}Multiple Fallbacks
Section titled “Multiple Fallbacks”{# Try multiple sources #}{% set title = page.customTitle ?? page.title ?? 'Untitled' %}
{# Or with if statements #}{% if page.customTitle %} {{ page.customTitle }}{% elseif page.title %} {{ page.title }}{% else %} Untitled{% endif %}Conditional Classes
Section titled “Conditional Classes”{# Single condition #}<div class="post {{ post.featured ? 'featured' : '' }}">
{# Multiple conditions #}<div class="post {% if post.featured %}featured{% endif %} {% if post.draft %}draft{% endif %} {% if post.urgent %}urgent{% endif %}">
{# Complex logic #}{% set statusClass = post.published ? 'published' : (post.draft ? 'draft' : 'pending') %}<div class="post {{ statusClass }}">Access Control
Section titled “Access Control”{# Check user permissions #}{% set canEdit = cms.user and ( "admin" in cms.user.roles or "editor" in cms.user.roles or cms.user.id == post.authorId) %}
{% if canEdit %} <a href="/edit/{{ post.id }}">Edit</a>{% endif %}Smart Defaults
Section titled “Smart Defaults”{# Provide sensible defaults #}{% set perPage = request.query.limit|default(10) %}{% set sortBy = request.query.sort|default('date') %}{% set order = request.query.order|default('desc') %}
{# Validate and constrain values #}{% if perPage > 100 %} {% set perPage = 100 %}{% endif %}