Skip to content

08 Printouts - Handlebars

SRS supports the Handlebars templating engine. Template files should be stored in the /templates directory of the application.

Execute

To execute a Handlebars template, use the following API:

HTTP
/api/srs/{id}/{template-name}.hbs.html

To create a new template with basic helpers: srs_administrator

HTTP
/api/srs/{id}/_new.hbs.html

You can also use the following extensions:

  • .hbs.html - HTML
  • .hbs.pdf - PDF
  • .hbs.csv - CSV
  • .hbs.txt - plain text
  • .hbs.xml - XML
  • .hbs.epp - EPP
  • .hbs.svg - SVG

Example data object

JavaScript
{
    dataset0: {        // object
        "field0": "some test <b>test</b>",
        "field1": "some test2",
        "field2": "some test3"
    },
    dataset1: [        // array
        {
            "field0": "some text4",
            "field1": "some text5",
            "field2": "some text6"
        }
    ],
    dataset2: []       // empty array
}

Handlebars FAQ

Built-in functions

  • isArray — checks whether a value is an array
Text Only
1
2
3
{{#if (isArray this)}}
...
{{/if}}
  • fnAdd — adds a number (useful for 1-based index display)
Text Only
1
2
3
{{#each items}}
  {{fnAdd @index 1}}
{{/each}}
  • fnSum — sums all values in a column of a dataset
Text Only
{{fnSum dataset column}}
  • isEqual — compares two values for equality; useful for cross-dataset filtering
Text Only
1
2
3
4
5
6
7
{{#each items}}
  {{#each ../files}}
    {{#if (isEqual this.commisionID ../commisionID)}}
    <img src="data:image/png;base64,{{path}}" />
    {{/if}}
  {{/each}}
{{/each}}
  • get — retrieves a property value from an object by key name
Text Only
{{get commandname "ret"}}
{{get srstranslation "ret"}}

When inside a loop, escape the dataset reference with ../:

Text Only
1
2
3
{{#each items}}
<div>{{get ../srstranslation label}}  {{label}}</div>
{{/each}}

Variables

  • @index Current iteration index (0-based)
  • @key Current key (for object iteration)
  • @first true on first iteration
  • @last true on last iteration
  • @length Total number of items in the array

Example:

Text Only
1
2
3
4
5
{{#each items}}
  <div {{#unless @last}}class="break"{{/unless}}>
  Hello
  </div>
{{/each}}

Iterate datasets

Text Only
1
2
3
{{#each this}}
  <li>{{@key}}</li>
{{/each}}

IF in Handlebars

Text Only
1
2
3
4
5
6
7
{{#if dataset2}}
 NOT VISIBLE - array is empty
{{/if}}

{{#if dataset0}}
  VISIBLE - object is not empty
{{/if}}
Text Only
1
2
3
{{#unless isValid}}
{{/unless}}
{{! You can also use {{else}} inside {{#if}} or {{#unless}} blocks }}

Raw text in Handlebars

Text Only
raw (unescaped HTML): {{{dataset0.field0}}}
html-escaped:          {{dataset0.field0}}

Generate CSV

Replace the space separator with any character, e.g. comma: {{#unless @last}},{{/unless}}

Text Only
1
2
3
{{#each api}}
{{#each this}}{{{this}}}{{#unless @last}} {{/unless}}{{/each}}
{{/each}}

Includes (images)

There are two ways to include images in a Handlebars template.

Direct reference to storage

Include images from any storage location using [[ and ]] tags:

HTML
<img src="data:image/png;base64,[[/api/core/storage/get/www/images/logo.png]]" />

SRS data object

Include images from the SRS data object using the tbase64 column type.

SRS definition:

XML
1
2
3
4
5
6
<srs>
  <itm model="column" type="tbase64" name="testimg" />
  <itm model="command" opts="dtsingle" name="settings">
    select '33d52ff9-9914-923c-10bd-3251ea2db555.png' testimg
  </itm>
</srs>

Template:

HTML
<img src="data:image/png;base64,{{{settings.testimg}}}" />

Comments

Text Only
{{! This comment will not appear in the output }}

Generic table (horizontal)

HTML
<table>
  <!--START Optional column widths -->
  <colgroup>
    <col style="width:20mm">
    <col style="width:40mm">
    <col style="width:60mm">
  </colgroup>
  <!--END Optional column widths -->
  <thead>
    <tr>
      {{#each dataset1.[0]}}
        <th>{{@key}}</th>
      {{/each}}
    </tr>
  </thead>
  <tbody>
    {{#each dataset1}}
      <tr>
        {{#each this}}
          <td>{{this}}</td>
        {{/each}}
      </tr>
    {{/each}}
  </tbody>
</table>

Generic table (vertical)

HTML
<table>
  <tbody>
    {{#each dataset1}}
      {{#each this}}
        <tr>
          <td>{{@key}}</td>
          <td><b>{{this}}</b></td>
        </tr>
      {{/each}}
    {{/each}}
  </tbody>
</table>

Template structure

  • Page size and margins are configured in the @page CSS section
  • The <header> element is repeated on every page
  • The <footer> element is repeated on every page

The following jq:page-template-* meta tags are experimental and available in dev versions only. They control background PDF overlays:

  • jq:page-template-first — applied to the first page
  • jq:page-template-last — applied to the last page
  • jq:page-template-all — applied to all pages
HTML
<!doctype html>
<html>
<head>
  <meta name="jq:page-width" content="210mm">    <!--DEFAULT-->
  <meta name="jq:page-height" content="297mm">   <!--DEFAULT-->
  <meta name="jq:margin-top" content="10mm">     <!--DEFAULT-->
  <meta name="jq:margin-bottom" content="10mm">  <!--DEFAULT; use 30mm with a background page-->
  <meta name="jq:margin-left" content="10mm">    <!--DEFAULT-->
  <meta name="jq:margin-right" content="10mm">   <!--DEFAULT-->
  <meta name="jq:footer-right" content="[page]/[topage]"> <!--DEFAULT-->
  <meta name="jq:footer-spacing" content="0">    <!--DEFAULT; use 19 with a background page-->
  <meta name="jq:page-template-first" content="/api/core/storage/get/appui/assets/first.pdf">
  <meta name="jq:page-template-last" content="/api/core/storage/get/appui/assets/last.pdf">
  <meta name="jq:page-template-all" content="/api/core/storage/get/appui/assets/background.pdf">
</head>
...

Example background page template: background.docx

Full template example with background image:

HTML
<!doctype html>
<html>
<head>
  <title>TITLE</title>
  <meta charset="utf-8" />
</head>
<body>

<header>HEADER SECTION</header>
CONTENT
<footer>FOOTER SECTION</footer>

<style>
  @page {
    width: 210mm;
    height: 297mm;
    margin-top: 20mm;
    margin-bottom: 20mm;
  }

  /* EXAMPLE: background image */
  body {
    background: url('data:image/png;base64,[[/api/core/storage/get/appui/assets/images/logo-background.png]]');
    background-repeat: no-repeat;
    background-position: 50% 300px;
    background-attachment: fixed;
    background-size: 100%;
    min-height: 800px;
  }
</style>

</body>
</html>