# Control Flow Guide
Master conditionals and loops in templates.
## If/Elsif/Else Conditionals
Control rendering based on conditions.
### Simple If
Render content only when condition is true:
```
{% if user.active %}
Welcome back!
{% endif %}
```
If `user.active` is falsy, the content is not rendered.
### If/Else
Provide alternative content:
```
{% if user.active %}
Welcome back!
{% else %}
Please activate your account
{% endif %}
```
### Multiple Conditions (If/Elsif/Else)
Check multiple conditions in order:
```
{% if user.role == "admin" %}
Admin Dashboard
{% elsif user.role == "moderator" %}
Moderation Panel
{% elsif user.role == "user" %}
User Dashboard
{% else %}
Guest Area
{% endif %}
```
The first true condition renders; rest are skipped.
### Nested Conditionals
Conditions can be nested:
```
{% if user %}
Name: {{ user.name }}
{% if user.email %}
Email: {{ user.email }}
{% endif %}
{% endif %}
```
## Conditions
### Comparisons
```
{{ 5 > 3 }} # true
{{ 5 < 3 }} # false
{{ 5 == 5 }} # true
{{ 5 != 3 }} # true
{{ 5 >= 5 }} # true
{{ 5 <= 10 }} # true
```
Use comparisons in if statements:
```
{% if age >= 18 %}
Adult
{% else %}
Minor
{% endif %}
```
### String Comparisons
```
{% if user.name == "Alice" %}
Hi Alice!
{% endif %}
{% if status != "active" %}
Inactive account
{% endif %}
```
### Logical Operators
Combine conditions with `and`, `or`, `not`:
```
{% if user.active and user.verified %}
Fully verified
{% endif %}
{% if user.admin or user.moderator %}
Staff member
{% endif %}
{% if not user.banned %}
Account is good
{% endif %}
```
### Complex Conditions
Use parentheses for clarity:
```
{% if (age >= 18 and verified) or admin %}
Can proceed
{% endif %}
{% if (status == "active") and not (role == "banned") %}
Show content
{% endif %}
```
## Truthiness
Values are evaluated as truthy or falsy:
**Falsy:**
- `nil` (null)
- `false`
- `""` (empty string)
- `[]` (empty list)
- `{}` (empty map/object)
**Truthy:**
- Everything else, including:
- `true`
- Non-empty strings: `"hello"`
- Numbers: `0`, `1`, `-1` (all numbers are truthy)
- Non-empty lists
- Non-empty maps
### Using Truthiness
Check if value exists:
```
{% if user.email %}
Email: {{ user.email }}
{% endif %}
```
This renders only if email is defined and not empty.
Check if list has items:
```
{% if items %}
{{ items | length }} items found
{% else %}
No items
{% endif %}
```
## Inline Conditionals
Render conditionals on a single line:
```
Status: {% if active %}Active{% else %}Inactive{% endif %}
{% if premium %}🌟{% endif %} {{ user.name }}
```
## For Loops
Iterate over collections.
### Basic Loop
```
{% for item in items %}
{{ item }}
{% endfor %}
```
This repeats the content for each item in the array.
### Loop Over Objects
```
{% for user in users %}
Name: {{ user.name }}
Email: {{ user.email }}
{% endfor %}
```
Each `user` has access to all properties.
### Nested Loops
```
{% for category in categories %}
Category: {{ category.name }}
{% for item in category.items %}
- {{ item }}
{% endfor %}
{% endfor %}
```
### Loop with Conditionals
```
{% for item in items %}
{% if item.available %}
<li>{{ item.name }}</li>
{% endif %}
{% endfor %}
```
## Loop Variables
Access loop metadata with `forloop`:
```
{% for item in items %}
{{ forloop.index }}: {{ item }}
{% endfor %}
```
### Available Variables
- **forloop.index** - Position (1-based: 1, 2, 3...)
- **forloop.index0** - Position (0-based: 0, 1, 2...)
- **forloop.first** - Boolean, true on first iteration
- **forloop.last** - Boolean, true on last iteration
- **forloop.length** - Total number of items
### Examples
**Number each item:**
```
{% for item in items %}
{{ forloop.index }}. {{ item }}
{% endfor %}
```
**Mark first and last:**
```
{% for item in items %}
{% if forloop.first %}
(First) {{ item }}
{% elsif forloop.last %}
(Last) {{ item }}
{% else %}
{{ item }}
{% endif %}
{% endfor %}
```
**Add separators:**
```
{% for item in items %}
{{ item }}{% unless forloop.last %}, {% endunless %}
{% endfor %}
```
Output: `Item1, Item2, Item3`
**Alternate rows:**
```
{% for item in items %}
{% if forloop.index0 | modulo(2) == 0 %}
<tr class="even">
{% else %}
<tr class="odd">
{% endif %}
<td>{{ item }}</td>
</tr>
{% endfor %}
```
**Progress indicator:**
```
{% for item in items %}
[{{ forloop.index }}/{{ forloop.length }}] {{ item }}
{% endfor %}
```
## Empty Loop Handling
Check if loop will run:
```
{% if items %}
{% for item in items %}
{{ item }}
{% endfor %}
{% else %}
No items to display
{% endif %}
```
Or with length filter:
```
{% if items | length > 0 %}
Found {{ items | length }} items
{% else %}
No items found
{% endif %}
```
## Control Patterns
### Conditional List Items
```
<ul>
{% for item in items %}
{% if item.active %}
<li>{{ item.name }}</li>
{% endif %}
{% endfor %}
</ul>
```
### Role-Based Display
```
{% if user.admin %}
<div class="admin-tools">
<button>Ban User</button>
<button>Edit Settings</button>
</div>
{% elsif user.moderator %}
<div class="mod-tools">
<button>Warn User</button>
</div>
{% endif %}
```
### Permission Checks
```
{% if user.can_edit_post %}
<button class="edit">Edit</button>
{% endif %}
{% if user.can_delete_post and post.owner == user.id %}
<button class="delete">Delete</button>
{% endif %}
```
### Status Indicators
```
{% for order in orders %}
<div class="order">
Order #{{ order.id }}
{% if order.status == "pending" %}
<span class="pending">Pending</span>
{% elsif order.status == "shipped" %}
<span class="shipped">Shipped</span>
{% elsif order.status == "delivered" %}
<span class="delivered">Delivered</span>
{% else %}
<span class="unknown">Unknown</span>
{% endif %}
</div>
{% endfor %}
```
### Pagination Indicators
```
Page {{ current_page }} of {{ total_pages }}
{% if current_page > 1 %}
<a href="?page={{ current_page | minus(1) }}">Previous</a>
{% endif %}
{% if current_page < total_pages %}
<a href="?page={{ current_page | plus(1) }}">Next</a>
{% endif %}
```
### Default Values
```
{% if user.bio %}
Bio: {{ user.bio }}
{% else %}
Bio: Not provided
{% endif %}
```
Or with filters:
```
Name: {{ user.name | default("Anonymous") }}
```
## Common Mistakes
### Wrong Operator
```
{# Wrong - string comparison #}
{% if items == [] %}
{# Right - check length #}
{% if items | length == 0 %}
{# Or - check truthiness #}
{% if items %}
```
### Missing Endif
```
{# Syntax error #}
{% if condition %}
Content
{# Correct #}
{% if condition %}
Content
{% endif %}
```
### Truthiness Confusion
```
{# 0 is truthy in Mau #}
{% if count == 0 %}
No items
{% endif %}
{# Not this #}
{% if not count %}
(0 is truthy, this won't work)
{% endif %}
```
## Advanced Patterns
### Ternary-like Pattern
Simulate ternary with inline if:
```
Status: {% if active %}Online{% else %}Offline{% endif %}
```
### Guard Clauses
Use early returns with negation:
```
{% if not user %}
Please log in
{% else %}
Welcome {{ user.name }}
{% endif %}
```
### Multi-Level Conditions
```
{% if user %}
{% if user.admin %}
Admin: {{ user.name }}
{% elsif user.active %}
Active: {{ user.name }}
{% else %}
Inactive: {{ user.name }}
{% endif %}
{% else %}
No user
{% endif %}
```
## Summary
| Feature | Syntax | Purpose |
|---------|--------|---------|
| If | `{% if condition %}` | Conditional rendering |
| Else | `{% else %}` | Alternative content |
| Elsif | `{% elsif condition %}` | Multiple conditions |
| For | `{% for x in y %}` | Iterate collections |
| forloop.index | `{{ forloop.index }}` | Current position (1-based) |
| forloop.first | `{{ forloop.first }}` | True on first item |
| forloop.last | `{{ forloop.last }}` | True on last item |
| and | `condition1 and condition2` | Logical AND |
| or | `condition1 or condition2` | Logical OR |
| not | `not condition` | Logical NOT |
## See Also
- [Template Language Reference](../reference/template-language.md) - Expression syntax
- [Variables Guide](variables.md) - Variable access patterns
- [Filters Guide](filters.md) - Using filters in conditions