Skip to content

Conditions

Conditions make one template work for many situations. Show a discount section only when there is a discount, print text in the customer’s language, or produce a different layout depending on a choice in the configurator.

There are three kinds of conditions:

KindUse it toExample
Inline conditionsPrint a word or value depending on a conditionTilbud or Quote
Removing elementsRemove a table row, paragraph, table or imageHide the discount table when there are no discounts
Conditional blocksShow or hide a larger section of the documentInclude a terms page only for export customers

Comparison operators

Every condition starts with a comparison. It is applied to the value of the tag:

OperatorMeaningExample
ifEQ(value)equal to{d.languageSlug:ifEQ('da')…}
ifNE(value)not equal to{d.countrySlug:ifNE('DK')…}
ifGT(value)greater than{d.conf_total:ifGT(100000)…}
ifGTE(value)greater than or equal to{d.form_submissions[0].quantity:ifGTE(2)…}
ifLT(value)less than{d.vat_total:ifLT(1)…}
ifLTE(value)less than or equal to{d.revision_number:ifLTE(1)…}
ifIN(value)contains (text or list){d.email:ifIN('@example.com')…}
ifNIN(value)does not contain{d.configuration_name:ifNIN('Draft')…}
ifEM()is empty (empty text, null, empty list){d.origin_request_id:ifEM()…}
ifNEM()is not empty{d.extra_fields[0].fields[slug='warranty'].value:ifNEM()…}

Inline conditions

Use show to print a text when the condition is true, and elseShow to print a text when it is false:

{d.languageSlug:ifEQ('da'):show('Tilbud'):elseShow('Quote')}
{d.vat_total:ifGT(0):show('incl. VAT'):elseShow('excl. VAT')}
{d.revision_number:ifGT(1):show('Revised quote'):elseShow('Quote')}
Result
Quote
excl. VAT
Quote

Without elseShow, the original value is printed when the condition is false. This is handy for fallbacks:

Payment terms: {d.extra_fields[0].fields[slug='payment'].value:ifEM():show('30 days net')}

Several values (switch)

Chain several conditions to map values to texts:

{d.countrySlug:ifEQ('DK'):show('Denmark'):ifEQ('SE'):show('Sweden'):ifEQ('DE'):show('Germany'):elseShow('Other')}
Result
Denmark

Show another field

Use a path instead of a fixed text to print another field. A path starting with a dot is relative to the same object:

{d.user.name:ifEM():show(.email)}

This prints the user’s name, or their email address if the name is empty.

Language-dependent text

Use languageSlug to translate static text in your template:

{d.languageSlug:ifEQ('da'):show('Gyldig til'):ifEQ('de'):show('Gültig bis'):elseShow('Valid until')}: {d.created_at:addD(30, 'day'):formatD('DD-MM-YYYY')}

Request fields also contain translated labels in translation, for example translation.da_name. To switch a whole table between languages, wrap a Danish and an English version in conditional blocks:

{d.languageSlug:ifEQ('da'):showBegin}
{d.extra_fields[0].fields[i].translation.da_name} {d.extra_fields[0].fields[i].value}
{d.extra_fields[0].fields[i+1]}
{d.languageSlug:showEnd}
{d.languageSlug:ifNE('da'):showBegin}
{d.extra_fields[0].fields[i].name} {d.extra_fields[0].fields[i].value}
{d.extra_fields[0].fields[i+1]}
{d.languageSlug:showEnd}

Removing rows, paragraphs and tables

drop(element) removes the element that contains the tag when the condition is true. The tag itself prints nothing.

ElementRemoves
rowThe table row
pThe paragraph
tableThe whole table
imgThe image
colThe table column
div, spanThe element (HTML templates)

keep(element) does the opposite: the element is kept only when the condition is true.

Hide empty request fields

Put the tag anywhere in the row. Rows without a value are removed:

Terms
{d.extra_fields[0].fields[i].name} {d.extra_fields[0].fields[i].value:ifEM():drop(row)}{d.extra_fields[0].fields[i].value}
{d.extra_fields[0].fields[i+1]}

Hide “No” answers

Configurators often contain yes/no questions such as Do you want to deselect the robot?. Remove those rows from a specification list:

ElementSelection
{d.form_submissions[0].form.data.elements[i].label}{d.form_submissions[0].form.data.elements[i].options[i].label} {d.form_submissions[0].form.data.elements[i].options[i].label:ifEQ('No'):drop(row)}
{d.form_submissions[0].form.data.elements[i].options[i+1]}
{d.form_submissions[0].form.data.elements[i+1]}

You can get the same result with a loop filter: options[i, label!='No'].

Hide a table when it’s empty

Put the tag in any cell of the table, for example the heading row:

{d.form_submissions[0].form.bom.tables[label='Discounts'].groups[0].rows:ifEM():drop(table)}

The table is also removed when the Discounts table isn’t part of the BoM at all.

Hide a paragraph

If you have a request field with the slug reference, print the line only when it’s filled in:

Your reference: {d.extra_fields[0].fields[slug='reference'].value}{d.extra_fields[0].fields[slug='reference'].value:ifEM():drop(p)}

Hide a missing image

When an option has no image, remove the image placeholder instead of showing an empty frame. Add both tags to the image’s alternative text:

{d.form_submissions[0].form.data.elements[i].options[i].image}{d.form_submissions[0].form.data.elements[i].options[i].image:ifEM():drop(img)}

See Images, Links and Barcodes.

Remove several rows or paragraphs

Add a number to remove the element and the ones that follow it. This works for row and p:

{d.vat_total:ifEQ(0):drop(row, 2)}

This removes the row with the tag and the next row, for example a VAT line and a total incl. VAT line.

Conditional blocks

To show or hide a larger part of a document, such as several paragraphs, tables and images, wrap it in showBegin and showEnd:

{d.form_submissions[0].form.data.elements[label='Quote Specification'].options[0].label:ifEQ('Seperate discount lines with prices'):showBegin}
Discounts
… discount table …
{d.form_submissions[0].form.data.elements[label='Quote Specification'].options[0].label:showEnd}

Everything between the two tags is included only when the condition is true. hideBegin and hideEnd do the opposite:

{d.vat_total:ifEQ(0):hideBegin}
VAT: {d.vat_total:formatN(2)} {d.currencyCode}
Total incl. VAT: {d.conf_total:add(d.vat_total):formatN(2)} {d.currencyCode}
{d.vat_total:hideEnd}

Layout switches from the configurator

A powerful pattern is to let the sales user choose the document layout in the configurator itself. The example quote has a Quote Specification element with the description “Based on what is chosen here, the pdf quote will generate differently”. Use its selected option to switch sections on or off:

{#spec = d.form_submissions[0].form.data.elements[label='Quote Specification'].options[0]}
{$spec.label:ifEQ('Seperate discount lines with prices'):showBegin}
… table with every discount line and its price …
{$spec.label:showEnd}
{$spec.label:ifNE('Seperate discount lines with prices'):showBegin}
… only the total discount …
{$spec.label:showEnd}

Because the value comes from a form element, you can add new layout options in the Form Builder without touching the rest of the quote flow.

Combining conditions

Use and and or between comparisons. Without a parameter, the next comparison is applied to the same value:

{d.conf_total:ifGT(100000):and:ifLT(500000):show('Mid-size project')}
{d.countrySlug:ifEQ('DK'):or:ifEQ('SE'):show('Nordic customer')}

Pass a path to compare a different value. Use a path starting with . for a field on the same object, or a full d. path for any field in the data:

{d.conf_total:ifGT(100000):and(d.countrySlug):ifEQ('DK'):show('Free installation included')}
{d.user.name:ifNEM():and(.email):ifNEM():show('Contact details available')}

A full d. path is also the way to use a quote-level value, such as d.languageSlug, in a condition inside a loop.