Skip to main content
Version: 2.5

Layout Designer

The Layout Designer is the visual editor for Layouts. You compose the document from blocks, bind data with Handlebars placeholders, and check the result against sample data while you work. The editor is built on GrapesJS and extended with tSM components for data binding, conditions, repeating tables and PDF page layout.

Open it from Output management → Layout, then create a Layout or open an existing one.

Layout Designer with test data on the left, the designer canvas and block library in the centre, and the live preview on the right

Screen layout​

The Layout detail has two tabs:

  • Layout – the editor itself.
  • Basic settings – Code, Name, Form, Type, Formatter document type, Formatter document size, Labels and Configuration Type. The properties are described in Output Management.

The header shows the Code and Name, the Save button (also Ctrl+S) and a preview action that depends on the document type:

Document typeActionWhat it does
PDFPreview pdfRenders the Layout with the test data into a real PDF. Use it to check page size, margins, headers, footers and page breaks.
EMAILSend a test emailRenders the Layout with the test data and sends it to the address you enter. Use it to check the result in real email clients.

For a Layout of type HTML, the Layout tab has three panels. The side panels can be resized and collapsed.

PanelContent
Test data (left)A JSON editor with sample input data. The designer offers these values in the data pickers and uses them for the preview.
Designer / Source code (centre)The visual canvas with the editor panels, or the HTML source of the Layout. Switch with the buttons at the top of the panel. SOURCE layouts have only the source code view.
Preview / Source code (right)The Layout rendered by the server with the test data, or the rendered HTML.

For a Layout of type FILE, the Layout tab shows the attachment area where you upload the document file instead of the editor.

Live preview​

The preview is rendered by the server with the same Handlebars engine that generates the real documents, so helpers and conditions behave as in production. It refreshes about one second after each change.

For large Layouts, turn on Disables automatic preview refresh in the header. The editor then stays responsive and the preview refreshes when you save or switch between the designer and the source code.

The preview is not the final PDF

The preview panel shows HTML in the browser. The PDF is produced by a different rendering engine with its own fonts, page handling and print styles. Always confirm the final result with Preview pdf. See PDF and Email Layouts.

Test data​

Paste a representative input JSON into Test data, ideally a real payload from the process or notification that will use the Layout. The designer flattens it into dot paths such as customer.primaryPerson.firstName and offers them in the Variable (testing data) pickers of the Handlebars, Condition block and Signature components, together with the sample value.

Test data is stored on the Layout for design purposes only. It does not affect documents generated in production.

Designer​

Toolbar​

The toolbar above the editor panels contains these buttons, from left to right:

ButtonAction
View componentsShows dashed outlines of all components, so empty cells and wrappers are visible.
FullscreenOpens the editor in fullscreen mode.
ImportOpens the Import template dialog. The HTML you paste there replaces the whole content of the canvas.
Toggle imagesTemporarily hides images in the canvas, which makes large Layouts faster to edit. Click again to show them.
Undo / RedoSteps back or forward through your changes.
Clear canvasRemoves all content after a confirmation.

The second group opens the side panel of the editor:

ButtonPanel
Style Manager (brush)CSS properties of the selected component, see Styling components.
Settings (gear)Properties (traits) of the selected component, for example the variable of a Handlebars component or the columns of a table.
Layer ManagerThe component tree. Use it to select nested elements, reorder them and find hidden or empty ones.
Blocks (plus)The block library. Drag a block onto the canvas to insert it.

Keyboard shortcuts​

ShortcutAction
Ctrl+SSave the Layout.
Ctrl+Z / Ctrl+Shift+ZUndo / redo.
Ctrl+C / Ctrl+VCopy / paste the selected component.
Delete, BackspaceDelete the selected component.
W / SSelect the previous / next sibling component.
A / DSelect the parent / first child component.

On macOS use ⌘ instead of Ctrl.

Block library​

Drag blocks from the Blocks panel onto the canvas. The tSM components are in the Extra category.

Structure and content

BlockInserts
1 Section, 1/2 Section, 1/3 Section, 3/7 SectionA table with one or two columns. Tables are the most reliable way to build columns in PDFs and emails.
Text, Text SectionEditable text. Double-click to edit; the text toolbar offers bold, italic, links, lists and indentation.
ImageAn image. Customer logos are usually embedded as base64 data.
Button, Link, Link BlockLinks styled as a button or text.
Divider, Quote, Grid Items, List ItemsPrepared content blocks, mainly for emails.
CheckboxA checkbox. Set whether it is checked in Settings.

tSM components (Extra)

BlockAvailable forPurpose
HandlebarsallA data placeholder, optionally with a formatting function. See Handlebars.
FieldallA static label followed by a Handlebars value on one line, for example Customer ID: {{customer.id}}.
Condition blockallShows content conditionally or repeats it for each item of a list. See Condition block.
TableallA table with an optional header and footer that can repeat its body rows for each item of a list. See Table.
SignatureallAn image whose content comes from base64 data, for example a customer signature.
DivallAn empty container for grouping content.
Custom CodePDFRaw HTML or Handlebars that the visual editor does not support.
Layout for PDFPDFThe page frame with header, main content and footer, and the page margins.
Paginator for PDFPDFThe current page number and the page count, for example 2 z 5.
Count of pages for PDFPDFThe total number of pages.
New page for PDFPDFA forced page break.

tSM components​

Select a component on the canvas and open Settings (gear) to edit its properties.

Handlebars​

The Handlebars component inserts one value into the document. Its settings have three parts:

  • Variable (testing data) – a path from the test data, shown with its sample value, or Custom expression for anything the picker cannot express.
  • Function – an optional helper applied to the value.
  • Parameters – additional arguments for helpers that need them. For Format date you choose the date format instead.

Settings of a Handlebars component: variable agreement.signedDate with the Format date function and the date format

The component writes {{function variable parameters}}, for example {{formatDate order.createdDate "dd.MM.yyyy"}}. A custom expression is written as is inside the braces, so {description} produces {{{description}}}, which prints HTML without escaping.

FunctionGenerated helperPurpose
PlaintextplaintextConverts HTML to plain text.
MarkdownmarkdownConverts Markdown to HTML. See the note below about triple braces.
HtmlToMarkdownhtmlToMarkdownConverts HTML to Markdown.
HtmlhtmlOutputs HTML without changes.
Format dateformatDateFormats a date: dateTime (dd.MM.yyyy HH:mm), dateTimeS, dateTimeMs, date (dd.MM.yyyy), time (HH:mm), timeS.
Seconds timesecondsTimeConverts seconds to hours, minutes and seconds, for example 1:1:1 for 3661.
Format currencyformatCurrencyOlder currency helper. For amounts use formatMoney as a custom expression, see the Handlebars Reference.
MathmathArithmetic, for example parameters "*" 1.21.
Replace, Replace regexreplace, replaceRegexReplaces text or a regular expression match.
CheckBox textcheckBoxTextRenders a checkbox followed by text.
ButtonbuttonRenders a link styled as a button. See the note below about triple braces.
User by Id, UserGroup by IduserById, userGroupByIdPrints the name of a user or user group.
Get ciselnik name by codegetCiselnikNameByCodePrints the name of a user register value. The helper expects the register code first, so write it as a custom expression, see below.

The helpers are described in the Handlebars Reference.

Markdown and Button need triple braces

The component always writes double braces, so Markdown produces {{markdown body}} and the generated HTML is escaped and printed as text. The same applies to Button. For formatted output choose Custom expression and enter {markdown body}, which produces {{{markdown body}}}.

The component always writes the variable before the parameters. Get ciselnik name by code needs the register code first, so write it as a custom expression, for example getCiselnikNameByCode 'Prostredi' order.environment.

Helpers that are not in the list, such as formatMoney or spel, are available through Custom expression as well, for example formatMoney order.total currency='EUR'.

Field​

The Field component is a label and a Handlebars value that stay on one line. Edit the label text directly on the canvas and select the value to set its variable. Use Field for pairs such as Order number: {{order.key}}. Suffixes such as a currency or a unit belong in a separate text element next to the Field.

Condition block​

The Condition block wraps content in a Handlebars block. Its settings are Function and Parameters (the condition or the list path):

FunctionGenerated markupUse
If{{#if condition}} … {{/if}}Show the content only when the condition is true.
If-else{{#if condition}} … {{else}} … {{/if}}Show one of two variants.
Each{{#each list}} … {{/each}}Repeat the content for each item of a list. Inside, paths are relative to the item.
With{{#with object}} … {{/with}}Shorten paths inside the block to the given object.

The designer shows the start, else and end markers as small labelled bars, so you can see where the block begins and ends. They are part of the HTML, so hide them in print output with @media print { .start-condition, .if-else-condition, .end-condition { display: none; } } when they break inline layouts in the PDF.

Conditions can use any helper from the Handlebars Reference:

{{#if (eq customer.type "FYZ")}} … {{/if}}
{{#if (and order.isPaid (not order.isCancelled))}} … {{/if}}
{{#if (ifEquals contract.isAmendment true)}} … {{/if}}
Compare booleans explicitly

A condition such as contract.isAmendment true is not a comparison: the second word is passed as an extra argument and the condition only tests contract.isAmendment. Use (eq a b) or (ifEquals a b) whenever you compare two values.

Table​

The Table component builds a table whose rows can be generated from a list. Its settings:

SettingMeaning
Number of Rows, Number of ColumnsSize of the table body.
Table Header, Table FooterAdds a <thead> or <tfoot> row. A PDF repeats the header on every page the table spans.
Each CellRepeats the body rows for each item of a list.
Array parameterThe list path for Each Cell, for example order.items.

With Each Cell turned on, the table gets two technical rows with {{#each order.items}} and {{/each}}. Keep them: they are hidden in the output and define what is repeated. Inside the body rows, bind cells to item properties such as {{name}} and {{price}}.

The result looks like this in the source code:

<table class="table-plugin" eachcell="true" eachparametercell="order.items">
<thead class="table-header-plugin">
<tr><th class="table-cell-th-plugin">Item</th><th class="table-cell-th-plugin">Price</th></tr>
</thead>
<tbody class="table-body-plugin">
<tr class="table-body-each-start-plugin"><td>{{#each order.items}}</td></tr>
<tr>
<td class="table-cell-plugin">{{name}}</td>
<td class="table-cell-plugin">{{formatMoney price}}</td>
</tr>
<tr class="table-body-each-end-plugin"><td>{{/each}}</td></tr>
</tbody>
</table>

Signature​

The Signature component shows an image from base64 data. Choose the variable that contains the image data (for example a signature captured in a form). The component writes src="data:image/png;base64,{{variable}}" for you, so the variable must contain only the base64 content without the data: prefix. Functions are not offered, because any formatting would corrupt the image data.

Layout for PDF​

Layout for PDF is the page frame of a PDF document. Every PDF Layout should start with it. It contains three fixed areas:

AreaContent
HeaderContent printed at the top of each page, for example a logo and the document title.
MainThe document body.
FooterContent printed at the bottom of each page, for example company details and the paginator.

Its settings are the page margins margintop, marginright, marginbottom and marginleft (defaults 150px, 1cm, 100px, 1cm). The top and bottom margins must leave enough space for the header and the footer. The paper size is taken from Formatter document size in Basic settings.

Whether the header and footer repeat on every page depends on the PDF rendering engine of the environment, see Running header and footer.

Paginator for PDF and Count of pages for PDF are filled in when the PDF is generated. In the designer they stay empty. New page for PDF forces a page break; use it only where the document really requires a new page, otherwise let the content flow.

Custom Code​

For PDF Layouts, Custom Code holds HTML or Handlebars that the visual editor cannot model, for example inline Handlebars inside a numbered list. Open the code editor from the component toolbar, edit the code and click Save. Scripts are not executed in the canvas.

Styling components​

The Style Manager edits the CSS of the selected component:

SectorProperties
DimensionWidth, height, maximum width, minimum height, margin, padding, and the display mode (Block, Inline block, Inline).
TypographyFont family, size, weight, letter spacing, colour, line height, alignment, decoration, style, vertical alignment, text shadow and white space handling.
DecorationsBackground, border radius, borders, border collapsing and background images.

The editor styles the selected component by its own ID. This keeps styles independent of each other: changing one cell does not change other cells. Styles defined in the source code with classes still apply and can be combined with the per-component styles.

Source code​

Switch the centre panel to Source code to edit the HTML directly. This is useful for:

  • pasting a Layout prepared outside tSM,
  • Handlebars constructs the designer does not model, such as whitespace control or nested helpers,
  • bulk edits such as renaming a data path in all places.

For PDF Layouts, the source starts with a generated block marked IMPORTANT - this block do not edit!!!. It holds the @page rule and the print rules and is regenerated from Layout for PDF and Formatter document size on every export, so change the margins and the paper size there, not in this block.

When you switch back to Designer, the source is parsed into components again. Keep the tSM components intact in the source: the class names (table-plugin, condition-block, layout-wrapper-pdf, …) and attributes (eachcell, function, condition, customexpression) are how the designer recognises them.

Worked example: customer agreement​

This example builds the Participant section of a contract.

  1. In Basic settings, set Formatter document type to PDF and Formatter document size to A4.

  2. Paste test data, for example:

    {
    "headlineName": "Electronic communications services",
    "customerType": "FYZ",
    "customer": {
    "primaryPerson": {
    "firstName": "Michal",
    "lastName": "Novák",
    "chars": { "titleBefore": "Bc.", "titleAfter": "MBA" }
    }
    }
    }
  3. Insert Layout for PDF. Put the logo into the header and a Paginator for PDF into the footer.

  4. In the main area, add a heading with a Field Agreement: {{headlineName}}.

  5. Add a Condition block with the function If and the condition (eq customerType "FYZ"), so the next part appears only for individuals.

  6. Inside it, insert a Table with a header and four columns (Title before, Name, Surname, Title after). Put Handlebars components into the body cells and choose the variables customer.primaryPerson.chars.titleBefore, customer.primaryPerson.firstName, and so on.

  7. Check the live preview, then click Preview pdf and review the real PDF.

  8. Save the Layout.

The resulting source of the conditional table:

{{#if (eq customerType "FYZ")}}
<table>
<tr>
<td>{{customer.primaryPerson.chars.titleBefore}}</td>
<td>{{customer.primaryPerson.firstName}}</td>
<td>{{customer.primaryPerson.lastName}}</td>
<td>{{customer.primaryPerson.chars.titleAfter}}</td>
</tr>
</table>
{{/if}}

Best practices​

  1. Start from real data. Test data copied from a real process makes the pickers accurate and the preview trustworthy.
  2. Build columns with tables. Section blocks and tables render consistently in PDF engines and email clients; floating or flex layouts often do not.
  3. Use the tSM components for data, conditions and repeating rows instead of hand-written Handlebars in text. They keep start and end markers in sync.
  4. Check the real output. The preview is HTML in a browser. Confirm PDFs with Preview pdf and emails with Send a test email.
  5. Move content to Templates. Texts that business users change belong in a Template, not in the Layout.

For print and email specifics, continue with PDF and Email Layouts.