Dynamically set the content of a cloned section

Section cloning in is a technique used to replicate a print section multiple times, each instance potentially featuring different personalization or a unique background image.

In most cases, the content of the section needs to be personalized. While the section may primarily need variable content from the data record, there are situations where this involves more than just replacing placeholders with data. For example, in documents like policy packages, specific content may be stored in snippets that need to be dynamically loaded and used as the content for the cloned section. These snippets usually include placeholders/expressions and even some business logic.

The following approach demonstrates how to replace the content of a section clone with the contents of a Handlebars snippet during the cloning process using a Control Script.

Basic section clone loop

First, we’ll create a Control Script and set up a loop to clone the section based on the detail table. The for…of loop is ideal for this task. The loop’s first parameter receives the value from the current iteration, which in our case is a record from the detail table. In the example below this information is stored in the policy variable. This data will be useful for naming the clone and for subsequent steps.

let policySection = merge.context.sections.Policies

for(let policy of record.Policies) {
      let clone = policySection.clone()
      clone.name = policy.ref
      policySection.addAfter(clone)
}

policySection.enabled = false

Loading the snippet

In this loop, the following snippet retrieves and personalizes a Handlebars snippet using the render() function from the Handlebars API. The detail record is set as the data scope for the snippet, allowing the field names from the detail record to be used directly in expressions. There is no need to extract data from the detail table using an index, as the data has already been captured by the for…of loop and, in this example, stored in the policy variable.

The following code sample stores the merged result in the content variable, which is then assigned to the cloned section’s content using the html() function.

let content = Handlebars.render(`snippets/policy.hbs`, policy)
clone.html(content)

The full example:

let policySection = merge.context.sections.Policies

for(let policy of record.Policies) {
      let clone = policySection.clone()
      clone.name = policy.ref
      let content = Handlebars.render(`snippets/policy.hbs`, policy)
      clone.html(content)
      policySection.addAfter(clone)
}

policySection.enabled = false

Loading a variable snippet

The example above uses a hard-coded path to a snippet located in the snippets folder of the template. In contrast, the following snippet uses the ref data field within a JavaScript template literal (backtick) to dynamically construct a path for a variable snippet.

let content = Handlebars.render(`snippets/${policy.ref}.hbs`, policy)
clone.html(content)

Variable content driven by the partial

Alternatively, one could refer to a static snippet as shown in the first example and load policies content using dynamic partials.

The following shows the contents of the policy.hbs snippet. It uses the partial call syntax to render and inject the respective content and an entry to load a partial dynamically by concatenating the path to a sub folder with the value of the ref field taken from the detail record.

<h1>{{policy}}</h1>

<!-- Generic policy information section -->
{{> snippets/partials/policy-details.hbs}}

<!-- Policy specific section -->
{{> (concat 'policies/' ref)}}

<!-- Generic sections -->
{{> snippets/partials/own-risk.hbs}}
{{> snippets/partials/premium.hbs}}
{{> snippets/partials/clauses.hbs}}
{{> snippets/partials/conditions.hbs}}
{{> snippets/partials/representative.hbs}}