Skip to main content

Loop blocks

When a block's argument is an array, the body runs once per element with that element pushed as the current context:

{{name}}, your comments:

{{#comments}}
{{author}}
wrote:
{{comment}}
{{/comments}}
Context and output

Context

{
"name": "George",
"comments": [
{
"author": "Alice",
"comment": "Nice presentation"
},
{
"author": "Bob",
"comment": "Thanks for the feedbacks"
}
]
}

Generated output

George, your comments:

Alice wrote:
Nice presentation
Bob wrote:
Thanks for the feedbacks

The blank line between the title and the first iteration is preserved verbatim; the {{#comments}} and {{/comments}} tags themselves consume their own lines because they are standalone.

The current item

Inside the loop, bare path expressions resolve against the current element. Two short forms refer to the element as a whole:

FormNotes
{{$this}}Bigodin canonical
{{this}}Handlebars-style alias
{{.}}Mustache-style implicit iterator
{{#keywords}}
-
{{$this}}
{{/keywords}}
Context and output

Context

{
"keywords": ["lorem", "ipsum", "dolor"]
}

Generated output

- lorem
- ipsum
- dolor

The three forms are interchangeable:

{{#keywords}}- {{.}}
{{/keywords}}

…produces the same output.

Empty arrays

An empty array is treated as falsy: the body of a {{#items}}...{{/items}} block does not run. Pair with {{else}} to render an empty-state message:

{{#comments}}
-
{{author}}:
{{comment}}
{{else}}
No comments yet.
{{/comments}}

The negated form {{^items}}...{{/items}} runs the body for an empty array; see Negated blocks.

Non-array values

If the value is not an array but is truthy and is an object, the block runs once with that object as context (see Context blocks). For other truthy values, the body runs once with the parent context unchanged. To force "treat this single value as the new context," use the {{#with x}}...{{/with}} block helper.

Iteration variables

Inside a loop, four @-prefixed variables expose iteration state: @index, @key, @first, @last. See Iteration variables.

Block params

A loop head can name the current item and index with as |item index|, which is handy for reaching them by name from nested loops:

{{#each rows as |row r|}}
{{#each row as |cell c|}}
{{r}},{{c}}:
{{cell}}
{{/each}}
{{/each}}

See Block params for the full rules.

Walking the context

A loop pushes a new context. To reach the surrounding context (the one outside the loop), use $parent or $root:

{{#comments}}
From
{{author}}
to
{{$parent.name}}:
{{comment}}
{{/comments}}

See Context blocks for the full set of context-walking variables.