Back to all How-tos

Dynamic Tables reinvented

Do you know how to create a dynamic table for an invoice and use nested detail data to show complementary information? Most will  be challenged to accomplish this seemingly simple task.

OL Connect 2020.1 introduces a range of new features to make this easier and it provides ways to create more sophisticated dynamic tables. It comes with a new Insert Dynamic Table wizard and puts new HTML attributes at your disposal. These attributes let you add data to your dynamic table and modify the table structure without writing a single script. And yes… it supports nested detail data.

In this article you’ll explore the new Insert Dynamic Table wizard and learn about the underlying HTML attributes. We will elaborate on various techniques to place product specifications below the name of the product in an invoice template.

Exploring the Insert Dynamic Table wizard

We’ll start with a basic invoice data file. Each record contains information about a recipient and the line items are stored in a detail table. The product may have an arbitrary number of specifications. These are provided as an HTML string and stored in a single field of the detail data (the Attributes field). The Data Model looks like this:

Data Model with detail data

First, create a new print template and import the Data Model. Next, use the Insert Dynamic Table icon on the toolbar to invoke the all new and improved wizard. Select the root detail table (detail) and click Next. The Dynamic Table Builder appears.

The Dynamic Table Builder’s Table area and its sublevels represent the structure of the HTML table. The image above shows the default setup for the detail table in sample data. The setup consists of a single row (<tr>), containing six data fields, each representing a table cell (<td>). The row is linked to the detail table and the fields are linked to the data fields of that detail record.

You can use drag-and-drop to rearrange the fields. Choose a Format option to change the presentation of the data value and select an Alignment option for the text. Click the Delete icon at the end of each line to remove the respective entry. Add fields, or an empty cell, via the Add icon (plus) at the Row level.

The merged result would look something like this:

Dynamic Table with standard layout

The following shows the table’s (simplified) HTML structure:

<table id="table" data-detail data-expander="2020">
 <thead>
  <tr>
   <td>Number</td>
   <td>Description</td>
   <td>UnitPrice</td>
   <td>Quantity</td>
   <td>Total</td>
  </tr>
 </thead>
 <tbody>
  <tr data-repeat="detail">
   <td data-field="Number">@Number@</td>
   <td data-field="Description">@Description@</td>
   <td data-field="Attributes">@Attributes@</td>
   <td data-field="UnitPrice">@UnitPrice@</td>
   <td data-field="Quantity">@Quantity@</td>
   <td data-field="Total">@Total@</td>
  </tr>
 </tbody>
</table>

Let’s have a look at the data attributes on the <tr> and <td> elements: data-repeat and data-field.

The data-repeat attribute on the <tr> element states the name of the selected detail table. Based on this information the row is cloned for each detail record in that table.
The data-field attribute on <td> elements associates the text content of that element with the stated data field name.  The data value is automatically added when generating output (or in Preview mode). This attribute is a substitute for the traditional table text scripts. Note that one could still write custom scripts to modify the value at the time of insertion, for example .

The data-field attribute is not limited to the <td> element. It can be used on any child element within repeated rows (i.e. <tr> elements with the data-repeat attribute). In the following HTML it is used in a <span> and a <strong> element:

<tr data-repeat="detail">
 <td>No. <span data-field="Number">@Number@</span></td>
</tr>
<tr data-repeat="detail">
 <td><span data-field="Value">@Value@</span> <strong data-field="Unit">@Unit@</strong></td>
</tr>

Multiple rows for the same detail record

With the new detail table logic it is also possible to have multiple <tr> elements for the same detail record. This allows us to place the Attributes field on a separate line, that is, in a second <tr> element. Clicking the Add icon at the Table level will add a new row to the table. Link the row to the detail table (via the drop-down) so that it is properly repeated. Subsequently use the Add icon on the Row level to add fields. Consider the following setup:

You’ll notice that both Rows are associated with the same detail table. Consecutive rows linked to the same detail table are treated as virtual group and repeated as such. The row with the most fields defines the number of columns in the table. The field names of that row are automatically copied to the header of the table.

The second row starts with an empty field so that the Attributes fields is in the second field. Since there are no other fields in the row, that second <td> element automatically spans across the remaining columns.

 

Below is the resulting HTML. Both <tr> elements repeat over the same detail record.

<table id="table" data-detail data-expander="2019">
 <thead>
  <tr>
   <td>Number</td>
   <td>Description</td>
   <td>UnitPrice</td>
   <td>Quantity</td>
   <td>Total</td>
  </tr>
 </thead>
 <tbody>
  <tr data-repeat="detail">
   <td data-field="Number">@Number@</td>
   <td data-field="Description">@Description@</td>
   <td data-field="UnitPrice">@UnitPrice@</td>
   <td data-field="Quantity">@Quantity@</td>
   <td data-field="Total">@Total@</td>
  </tr>
  <tr data-repeat="detail">
   <td data-field=""></td>
   <td colspan="4" data-field="Attributes">@Attributes@</td>
  </tr>
 </tbody>
</table>

The following image shows the resulting table in the Design mode. Formatting was added (via CSS) to make the product text bold and to add a gray border to the bottom of the row that holds the product specifications.

In Preview mode, this is the result:

Dynamic Table with extra row and custom layout

Handling nested detail data

So far all data was stored in a standard detail table. Let’s take a look at how things work when the Attributes are stored in a nested (sub) detail table. The following image shows the Data Model for this scenario.

Data Model with nested detail table

As you have seen in the previous example, the Dynamic Table Builder allows you to add multiple rows and select a detail table for each row. In the following image a second row was added and associated with the detail.attributes table. The second Field entry references the Attribute field of that nested detail level. Again we use the empty field trick to push the actual data to the second column.

The following image shows the merged template. The Show Edges feature was activated to show the individual table rows for each record in the attributes table.
This approach allows the pagination algorithm to add page breaks between attribute rows.

Page break between attribute rows

Repeating a line in case of a page break

You may want a product line to be repeated when its attributes run over multiple pages. In order to get that repetition, first add an extra row in the Dynamic Table Builder, and link it to the detail table. Then change the “Initial” setting to Before a page break, After a page break, or before and after a page break (All).

Avoiding page breaks

Instead of repeating a product line you might want to avoid page breaks in the nested detail tables altogether. One can use the page-break-before and page-break-after CSS properties to achieve this. The Dynamic Table Builder allows to assign classes to rows. If we add the custom class attributes to the detail.attributes row, the following CSS rule will prevent page breaks before attributes rows:

tr.attributes {
  page-break-before: avoid;
}

Using this technique product and attributes lines always stay together.

Backward compatibility

Dynamic tables created in older versions of OL Connect render as they did before. They do not use and cannot be converted to use the new table expander logic.

Leave a Reply

Your email address will not be published. Required fields are marked *