# Control structures

> Reference for OneFuse Jinja2 control structures including for loops, if statements, and variable assignment

---

Site [llms.txt](/llms.txt)

---

A control structure refers to all those things that control the flow: conditionals, for-loops, as well as assignments.

Control structures appear inside `{% ... %}` tags.

## For

Loop over each item in a sequence.

```jinja2
{# List users provided in a variable called 'users' #}
{% for user in users %}
  {{ user.username | e }}
{% else %}
  {# Optional else block if no iteration took place because sequence was empty or the filtering removed all items from the sequence. #}
  No users found.
{% endfor %}

{#
Unlike other for loops, you cannot break or continue in a loop. Instead, use filters
#}

{% for user in users if not user.hidden %}
  {{ user.username |e }}
{% endfor %}
```

### Special variables

Access special variables inside a for-loop block.

| Variable | Description |
| --- | --- |
| `loop.index` | The current iteration of the loop (1 indexed). |
| `loop.index0` | The current iteration of the loop (0 indexed). |
| `loop.revindex` | The number of iterations from the end of the loop (1 indexed). |
| `loop.revindex0` | The number of iterations from the end of the loop (0 indexed). |
| `loop.first` | Returns `true` if first iteration. |
| `loop.last` | Returns `true` if last iteration. |
| `loop.length` | The number of items in the sequence. |
| `loop.cycle` | A helper function to cycle between a list of sequences. |
| `loop.depth` | Indicates how deep in a recursive loop the rendering currently is. Starts at level 1. |
| `loop.depth0` | Indicates how deep in a recursive loop the rendering currently is. Starts at level 0. |
| `loop.previtem` | The item from the previous iteration of the loop. Undefined during the first iteration. |
| `loop.nextitem` | The item from the following iteration of the loop. Undefined during the last iteration. |
| `loop.changed(*val)` | Returns `true` if previously called with a different value (or not called at all). |

---

## If

Test if a variable is defined, not empty and not false.

`if` can be used as an [inline expression](/docs/onefuse/templating/expressions/#if-expression) and [for-loop](#for) filtering. You can also use more complex [Expressions](/docs/onefuse/templating/expressions/).

```jinja2
{% if foo == 1 %}
  foo is 1
{% elif foo == 2 %}
  foo is 2
{% else %}
  foo is not 1 nor 2
{% endif %}
```

---

## Assignment

Assign values to variables.

```jinja2
{% set foo = "Hello world!" %}
```

### Block assignments

Capture contents of a block into a variable.

```jinja2
{% set foo %}
Hello
world
!
block
{% endset %}
```

### Scoping behavior

When variables are set within a block, the variable values are not scoped to show outside of the block (for example, for-loops).

```jinja2
{# Cannot scope variables outside of blocks #}
{% set iterated = false %}
{% for item in sequence %}
  {{ item }}
  {% set iterated = true %}
{% endfor %}

{# Print iterated variable #}
{{ iterated }}

=> false

{# Use alternative constructs like the loop-else block #}
{% for item in sequence %}
  {{ item }}
{% else %}
  Did not iterate
{% endfor %}
```
