Source Link: https://help.lob.com/print-and-mail/designing-mail-creatives/maximizing-engagement/dynamic-personalization/advanced-templating-handlebars/dynamic-table-tutorial
--- description: >- In-depth tutorial of how to neatly break apart sets of data into paginated segments --- # Dynamic table tutorial For certain use cases, you may need a table of dynamic length. These tables should not have rows that are divided between pages, and you may need a header for each page. This tutorial breaks down how to create them using the [Handlebars engine](). ### The tools #### [\{{withGroup\}}](..#withgroup) This will allow you to group elements into the subarrays that will make each page of the dynamic table #### [\{{each\}}](..#each) This allows you to iterate over each "row" in the withGroup subarrays. #### [\{{if\}}](..#if) In this case, we're using the if statement to evaluate whether or not we're at the absolute final row for the entirety of our table ### The template CSS / HTML ```css body { width: 8.5in; height: 11in; margin: 0 } .page { page-break-after: always; position: relative; width: 8.5in; height: 11in; } table { border-spacing: 5px; margin-left: .35in; } td { vertical-align: top; text-align: left; } tr { font-size: 14; } tr:nth-child(odd) { background-color: #e4e4e4; } ``` ```html {{#withGroup items 9}}
--- description: >- In-depth tutorial of how to neatly break apart sets of data into paginated segments --- # Dynamic table tutorial For certain use cases, you may need a table of dynamic length. These tables should not have rows that are divided between pages, and you may need a header for each page. This tutorial breaks down how to create them using the [Handlebars engine](). ### The tools #### [\{{withGroup\}}](..#withgroup) This will allow you to group elements into the subarrays that will make each page of the dynamic table #### [\{{each\}}](..#each) This allows you to iterate over each "row" in the withGroup subarrays. #### [\{{if\}}](..#if) In this case, we're using the if statement to evaluate whether or not we're at the absolute final row for the entirety of our table ### The template CSS / HTML ```css body { width: 8.5in; height: 11in; margin: 0 } .page { page-break-after: always; position: relative; width: 8.5in; height: 11in; } table { border-spacing: 5px; margin-left: .35in; } td { vertical-align: top; text-align: left; } tr { font-size: 14; } tr:nth-child(odd) { background-color: #e4e4e4; } ``` ```html {{#withGroup items 9}}
{{#each this}}
{{#if superlast}}
{{/if}}
{{/each}}
{{/withGroup}}
```
Within our template, let's place a table and use `{{withGroup}}`to break apart our `rows` merge variable parameter into `9` groups per page, or `{{withGroup rows 9}}`. We have chosen `9` because we have already determined that any more rows than this would spill into the following page. This of course, means that going into this, you'll need an idea of how much space each row will take.
Then, we'll use `{{each}}` to iterate over each of the `9` rows per page and access nested elements within the row.
Lastly, we'll use `{{if superlast}}` to evaluate if the row we're iterating over is truly the last in the spreadsheet. In our JSON, the last item of `rows` will have parameter `superlast` equal to true, which triggers this portion off. This logic enables the ability to append a footer to the last page in our spreadsheet.
You'll notice that within this section, we include `{{../../first_name}}`, this is because we're referencing the merge variable `first_name` two scopes up (one out of the each loop, one out of the withGroup loop).
### The JSON merge variable data
When we're ready to `merge_variables` , we'll need to include our complete array of rows. Note the last item in "rows" has an extra parameter `superlast` which is set to `true`
```json
"merge_variables": {
"first_name": "Michael",
"rows": [
{
"service": "Eye Exam",
"provider": "Dr. Mobius",
"cost": "200",
"dateOfService": "2/23/23"
},
{
"service": "General Checkup",
"provider": "Dr. Murphey",
"cost": "300",
"dateOfService": "1/23/23"
},
{
"service": "Perscription Evaluation",
"provider": "Dr. Mario",
"cost": "200",
"dateOfService": "1/19/23"
},
...
...
{
"service": "Blood Test",
"provider": "Dr. Morbius",
"cost": "100",
"dateOfService": "1/22/23",
"superlast": true
},
]
}
```
### Making the requests
Once we've implemented the logic for dynamic tables into our own templates, we can post to the `/templates` endpoint, making sure that the `engine` parameter is set to `handlebars`. This will provide back a template reference id. We can then use this in the `file` parameter for the `/letters` endpoint. For more information on [advanced template creation](..#creating-a-template) and [request submission](..#create-a-mailpiece-using-handlebars) see the associated hyperlinks.
| Your Invoice | |||||
|---|---|---|---|---|---|
| Date of Service | Service | Provider | Charge | ||
| {{dateOfService}} | {{provider}} | {{service}} | ${{cost}} | ||
| Thank you for choosing Lob for your services {{../../first_name}}! | |||||