Listing a collection of items
Some emails need to list things: the items in an order, the sessions someone booked, the files attached to a ticket. Rather than building a merge tag for every possible row, Tarvent lets you send a collection of items and repeat a piece of your template once for each one. This guide covers how that works and how to build a typical order confirmation.
In this guide, you'll find:
- What a collection is
- Sending a collection
- Repeating content for each item
- Building an order confirmation
- Knowing where you are in the list
- When the list is empty
- FAQs
1 What a collection is
A collection is a list of items, where each item has its own set of values. An order with three products is a collection of three items, each with a name, a quantity, and a price.
This is different from an ordinary merge tag. {{Contact.firstName}} holds one value. A collection holds many, and you do not know in advance how many, so your template describes what one item looks like and Tarvent repeats it.
2 Sending a collection
Collections are sent as a variable on a transactional message, in the same place as your other variables. The difference is that the value is a list rather than a piece of text:
{ "name": "items", "value": [ { "name": "Rope", "qty": 2, "price": 4.50 }, { "name": "Anvil", "qty": 1, "price": 120.00 } ] }
Important: Send the list as a real list, not as text. If you convert it to a string first, for example by putting quotes around the whole thing, Tarvent receives one long piece of text rather than a list of items, and your template will show nothing.
3 Repeating content for each item
Wrap the part of your template you want repeated in {{#each}} and {{/each}}, naming the collection you sent:
{{#each tx.variabledata.items}} ... {{/each}}
Inside those tags, {{this.name}} refers to the current item's name value, {{this.qty}} to its quantity, and so on. The word this always means "the item we are on right now".
4 Building an order confirmation
Put the repeating block inside your table so that one row is produced per item:
<table>
{{#each tx.variabledata.items}}
<tr>
<td>{{this.name}}</td>
<td>{{this.qty}}</td>
<td>{{multiply this.qty this.price precision=2}}</td>
</tr>
{{/each}}
</table>
Note the third column. The other merge tags work normally inside a repeating block, so Multiply can calculate each line total from that item's own quantity and price. You do not have to send a pre-calculated total for every row.
5 Knowing where you are in the list
Inside a repeating block you can also use:
{{@index}}, the item's position starting at 0.{{@first}}and{{@last}}, useful for styling the first or last row differently, or for deciding where to put separators.
For example, to add a border to every row except the last, wrap the border style in {{#unless @last}}.
6 When the list is empty
If the collection has no items, the block simply produces nothing and the rest of your email sends normally. If you want to say something in that case, add an {{else}}:
{{#each tx.variabledata.items}}...{{else}}No items on this order.{{/each}}
7 FAQs
My list shows nothing at all. What is wrong?
The most common cause is sending the list as text instead of as a real list. Check that the value in your request is a list, not a quoted string.
The second most common cause is capitalization. The tx.variabledata. part is forgiving and can be typed in any case, but your own variable name must match exactly what you sent. If you sent a variable called items, then {{#each tx.variabledata.Items}} finds nothing.
Can I sort or filter the list in the template?
Not currently. Items appear in the order you send them, so sort them in your own application before sending.
Can I use this in a campaign as well as a transactional message?
Repeating blocks work anywhere the template engine runs, but collections are supplied per message, which makes them a natural fit for transactional email such as order confirmations and receipts.
Can I nest one list inside another?
Yes. Inside a repeating block, a value that is itself a list can be repeated with another {{#each}}.
How do I use a value from outside the list, such as the order number?
Inside a repeating block, merge tags refer to the current item, so {{tx.variabledata.orderNumber}} will not find anything there. Put @root. in front to start again from the top:
{{#each tx.variabledata.items}}{{@root.tx.variabledata.orderNumber}}: {{this.name}}{{/each}}