Back to Home

Iterations

Repeat table rows and list items once per child record — including nested parent-child hierarchies, row numbering, and scoped subtotals.

Iteration is how a single template row turns into many rows at generation time. When an element contains a merge token that points at a collection of child records — the line items under an opportunity, the contacts under an account — that element repeats once per record.

You do not configure anything special: iteration happens automatically wherever a child-record token appears. This page explains the behavior so you can design templates around it.


Repeating table rows

In a Table, put a child-record token in a body row. That row expands into one row per record.

| Product                              | Qty                            | Amount                          |
|--------------------------------------|--------------------------------|---------------------------------|
| {{OpportunityLineItem.Product2.Name}}| {{OpportunityLineItem.Quantity}}| {{OpportunityLineItem.TotalPrice}}|

With three line items on the record, this renders three body rows.

Header rows stay static. Any rows above the first row that contains a child token are treated as headers and rendered once, as-is.

Single template body row expanding into one row per line item with the header row kept once A single template body row expands into one row per line item; the header row is kept once.


Repeating list items

A List item containing a child token expands the same way — one bullet per record.

• {{Contacts.Name}} — {{Contacts.Title}}

renders one bullet for each contact returned.

List item expanding into one entry per child record A list item expands into one entry per child record.


Nested (parent-child) hierarchies

Iterations nest. A table can list each parent record followed by its own children — for example, each opportunity followed by that opportunity's line items. Each level expands within the scope of its parent, so inner rows only show records belonging to the current outer record.

This works to arbitrary depth (Account → Position → Lot → Transaction), with each level scoped to the one above it.

Two-level table showing each opportunity row followed by its own line-item rows A two-level table: each opportunity row is followed by its own line-item rows.


Row numbering with index

Inside a repeating element, the index token gives the current record's 1-based position:

{{Contacts.index}}. {{Contacts.Name}}

renders 1. Ada Lovelace, 2. Alan Turing, and so on. Use it for numbered lists or a "#" column in a table.


Subtotals and aggregates

Aggregate tokens (count, sum, min, max, avg) summarize a collection into one value, and they are scoped correctly inside iterations. A subtotal placed inside a per-opportunity group sums only that opportunity's own line items, while a grand total placed outside sums across all of them.

Subtotal for this opportunity: {{OpportunityLineItem.sum(TotalPrice)}}
Grand total: {{Opportunities.sum(OpportunityLineItem.TotalPrice)}}

See Merge Field Syntax → Aggregates for the full list.


Empty collections

If a parent has no matching child records, the repeating rows or list items simply produce no output — no empty row, no error. If you need a "no records" message, add it as a separate element with a conditional visibility rule that shows when the collection is empty.

Preview note: In the builder preview, child collections are capped to a small number of rows so previews stay fast. The full set is rendered when the document is generated.


See also