Iteration

The {#each} block iterates a collection and renders its contained content once per item.

Basic syntax

{#each Collection}
…content rendered once per item, with $ pointing at the current item…
{/each}
Data:
var person = new
{
    Employer = "Hat Trick Labs",
    Certifications = new[] { "mcse", "mcitp", "mcts" },
    Name = new { First = "John", Last = "Doe" }
};
Template:
Hello {Name.First} {Name.Last},

{#if Certifications}
We see you currently hold the following certs:
  {#each Certifications}
  - {$}
  {/each}
{/if}
{#if !Certifications}
  - We see you currently do not have ANY certs...
{/if}
Result:
Hello John Doe,

We see you currently hold the following certs:
  - mcse
  - mcitp
  - mcts

A {#each} bound to null or an empty collection emits nothing — pair with {#if !Collection} for an empty-state branch, as shown above.

Scope inside an each block

Inside an {#each} block, $ shifts to the current item. Use {$} directly for scalar collections; access properties with {Name} or {$.Name} for object collections.

Iterating an array of objects:
var data = new
{
    Rows = new[]
    {
        new { Name = "Alice", Score = 92 },
        new { Name = "Bob",   Score = 88 }
    }
};
Template:
{#each Rows}
{Name}: {Score}
{/each}
Result:
Alice: 92
Bob: 88

What can be iterated

{#each} works on any object that implements System.Collections.IEnumerable. That includes:

  • Arrays (T[], object[])
  • List<T>, HashSet<T>, and other generic collections
  • IDictionary (each iteration yields a DictionaryEntry/KeyValuePair)
  • Any custom type implementing IEnumerable or IEnumerable<T>
Strings are enumerable too. string implements IEnumerable<char>, so {#each} over a string iterates character-by-character. If you want to iterate words or lines, split first via a lambda and iterate the resulting collection.

Reaching outer scope

Once inside an {#each} block, the outer scope is still accessible. There are three ways to reach it:

  • Walk back with ..\{..\Employer} reaches one scope outward; chain for multiple levels: {..\..\Title}, {..\..\..\Root}. See Scope Chain Walk.
  • Declare a variable in the outer scope{?var:employer = Employer} before the each block, then {:employer} inside. Often the cleanest option, especially across multiple levels. See Variables.
  • Pass a lambda argument from the outer scope{(..\Employer, $) => formatBadge}.

Nested iteration

{#each} blocks can be nested. Each level starts a fresh local scope; the inner $ shadows the outer $. See Variables for iteration lifetime rules and Stack Depth Limit for nesting limits.

Whitespace

Like all block tags, {#each} emits a newline at each delimiter by default. Use - trim markers ({-#each …-}, {-/each-}) or the engine-level TrimWhitespace to control output formatting. See Whitespace Control.

Next steps