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
- mctsA {#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: 88What 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 collectionsIDictionary(each iteration yields aDictionaryEntry/KeyValuePair)- Any custom type implementing
IEnumerableorIEnumerable<T>
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
- Scope Chain Walk — the
..\operator for reaching outer scopes - Variables — accumulate values across iterations
- Lambda Expressions — sort, group, or filter a collection before iterating