Helpers for receipt templates

Use these helpers to build receipt templates.

Receipt templates support both built-in Handlebars helpers and custom helpers specific to receipts. This page lists the helpers, their purpose, and examples.

Overview

  • Use built-in helpers for generic control flow.
  • Use custom helpers for receipt and device-specific tasks (for example, grouping line items or sending printer commands to registered peripherals).
  • Pass only the required data to keep templates readable and maintainable.

Handlebars helpers

Basic block helpers

#each

Iterate over array items or object properties.

{{#each items}}
  {{@index}}:
  {{this.name}}
  -
  {{this.price}}
{{/each}}
Special variables inside #each:
  • @index: zero-based index of the current item in the array
  • @key: current property name when iterating over object properties
  • @first: true if this is the first item
  • @last: true if this is the last item
  • this: references the current item
  • ../: access parent context

#if

Conditionally render content when an expression evaluates to true.

{{#if customer.name}}
  Welcome,
  {{customer.name}}!
{{else}}
  Welcome, Guest!
{{/if}}

#unless

Inverse of #if. Renders content when an expression evaluates to false.
{{#unless paid}}
  Payment Required
{{/unless}}

#with

Create a new context scope to shorten property paths.

{{#with customer}}
  {{name}}
  -
  {{email}}
{{/with}}

Currency formatting

formatCurrency

Format monetary values using Dinero.js with the configured currency settings. All currency values are handled using Dinero.js for precise calculations.
{{formatCurrency amount 'numeric'}}
{{! Formats without currency symbol }}
{{formatCurrency amount}}
{{! Formats with currency symbol }}

Parameters for this helper include the following:

  • amount: Dinero.js object representing the monetary value.
  • format (optional): use numeric to output only the amount without a currency symbol.

Item grouping

groupByFacet

Group line items by a facet and calculate totals per group.

{{#groupByFacet line_items 'facetName'}}
  {{groupKey}}
  ({{totalQuantity}}
  items) subtotal:
  {{formatCurrency subtotal}}
{{/groupByFacet}}

Block context properties:

  • groupKey: facet value for the group
  • totalQuantity: total number of items in the group
  • subtotal: Dinero.js object for the group total
  • items: array of grouped items

Printer commands

barcode

Generate commands to print a Code 128 barcode including Human Readable Interpretation (HRI).

{{barcode value}}

Parameters for this helper include the following:

  • value: data to encode

Text formatting

truncate

Truncate text to a maximum length at a word boundary and append an ellipsis. Helps content fit within the printer width.

{{truncate description 20}}

Parameters for this helper include the following:

  • str: string to truncate
  • len: maximum length before truncation

Custom conditional helpers

You can nest custom conditional helpers for compound conditions.

if_gt (greater than)

Render content if the value is greater than the threshold.
{{#if_gt value threshold}}
  Content shown if value > threshold
{{/if_gt}}

if_gte (greater than or equal to)

Render content if value is greater than or equal to the threshold.
{{#if_gte value threshold}}
  Content shown if value >= threshold
{{/if_gte}}

if_lt (less than)

Render content if value is less than the threshold.
{{#if_lt value threshold}}
  Content shown if value < threshold
{{/if_lt}}

if_lte (less than or equal to)

Render content if the value is less than or equal to the threshold.
{{#if_lte value threshold}}
  Content shown if value <= threshold
{{/if_lte}}

if_eq (equal)

Render content if value strictly equals threshold.
{{#if_eq value threshold}}
  Content shown if value === threshold
{{/if_eq}}

if_ne (not equal)

Render content if value does not strictly equal threshold.
{{#if_ne value threshold}}
  Content shown if value !== threshold
{{/if_ne}}

Example combining built-in and custom helpers

The following example uses grouping, conditional helpers, truncation, currency formatting, and a barcode. It assumes device peripherals (for example a printer) are already registered.

{{! Logo at the top }}
{{logo 1 1}}

{{#if store.name}}
  {{store.name}}
{{else}}
  Default Store
{{/if}}

{{! Group items by product type }}
{{#groupByFacet line_items 'productType'}}
  ===
  {{groupKey}}
  ===

  {{#each items}}
    {{! Show item number for non-first items }}
    {{#unless @first}}
      {{@index}}.
    {{/unless}}
    {{truncate description 20}}

    {{! Format price based on amount }}
    {{#if_gt price.amount 10000}}
      **{{formatCurrency price}}**
    {{else}}
      {{formatCurrency price}}
    {{/if_gt}}
  {{/each}}

  {{#if_gt totalQuantity 1}}
    Group Total ({{totalQuantity}}
    items):
    {{formatCurrency subtotal}}
  {{/if_gt}}
{{/groupByFacet}}

{{! Only show barcode if order number exists }}
{{#with order_number}}
  {{barcode this}}
{{/with}}

Best practices

Follow these practices when building receipt templates:

  • Truncate long text to avoid unintended wrapping.
  • Use conditional helpers to cover pricing or quantity edge cases.
  • Group related items with groupByFacet for readability.
  • Use built-in context variables (@index, @first, @last) for positional logic.
  • Use ../ to access a parent context inside nested blocks.
  • Combine built-in and custom helpers instead of adding complex logic to a single helper.
  • Use the appropriate currency formatting based on display context.

Troubleshooting

If a receipt template does not render as expected, check the following:

SymptomResolution
Currency output looks wrongEnsure each price is a Dinero.js object and not a raw number.
Nested data not foundConfirm parent references use ../ at the correct depth.
Grouping empty or incorrectVerify the facet name string matches the data exactly.