Document templates
Document Templates
This guide documents how to author the HTML body of an Document Template. The body is a LiquidJS template that is rendered client-side & server-side, against the document's data.
It applies to documents shown in the record File viewer.
1. How rendering works
Your template is plain HTML with Liquid tags (
{{ ... }},{% ... %}).It is rendered against a context (the variables below) using LiquidJS with a set of custom filters (section 4).
Rendering happens in the browser from the document's stored data, so it works offline and re-renders live when the user changes the selection.
All standard LiquidJS tags and filters are available (
if,for,assign,unless,case,capture,json,default,date,upcase, …) in addition to the custom filters documented here.If the template fails to compile/render, the viewer shows an error card instead of the document.
Page format / orientation (A4, portrait, …) are template settings, not Liquid variables. They control the rendered page size and the PDF export.
2. Key conventions
2.1 Variable keys use underscores (not dots)
Record fields are keyed by their cube path with dots replaced by underscores. A field whose cube path is Tab_8880.prop878 is read as:
2.2 Label values are encoded as id||name||image
id||name||imageMany fields (foreign keys, labels) hold a packed string id||name||image. Use the extractLabelValue filter to pull out a part:
3. Available variables
record
object
The document's record (fields, underscore-keyed)
user
object
The current user
org
object
The current organisation
selections
array
The selected records (+ quantity)
all_records
array
Every record (+ optional quantity)
available_actions
array
Every record, display-formatted
record
recordThe record the document is attached to. Keys are the record's fields in underscore form (see 2.1). Values are raw cube values; label-type values use the id||name||image encoding.
For a fanOut document the record is the merge of the parent and the drilled-into record (e.g. both Store.* and StorePromo.* fields), so both sets of fields are addressable:
user
userThe signed-in user. Reliable fields:
user.firstName
"Jane"
user.lastName
"Doe"
user.email
"jane@acme.com"
org
orgThe current organisation. Reliable fields: org.id, org.name.
selections
selectionsThe records the user has selected in the selection panel. Re-computed live as the selection changes. Each entry:
Iterate it with getSelectedRecords (recommended — see below) so each item is flattened to its record fields plus quantity:
For records produced from an Object Link,
metadata.category,metadata.bucketandmetadata.leverare all the Object Link's name.
all_records
all_recordsSame shape as selections, but contains every record (selected or not). quantity is the entered number when present, otherwise null. Use it when you want to list everything regardless of selection. Pair it with getRecordsWithQuantity or getSelectedRecords:
available_actions
available_actionsEvery record, pre-formatted for display. Each entry:
Use filterAvailableActions to narrow by category/lever:
Limitation:
formatted.innerContent(server-side Markdoc over facets) is not reproduced client-side and is always an empty string.label,tags,scoreandoriginalare available.
4. Custom filters
extractLabelValue
extractLabelValueParse an id||name||image value. Optional arg: "name" | "id" | "image" (default returns name, falling back to id).
getRecordLabel
getRecordLabelGiven a record object, return the value of its first key ending in label.
formatNumber
formatNumberFormat a number with a numeral.js format string.
parseFloat
parseFloatCoerce a string to a float (useful before arithmetic).
generateBarcodeUrl
generateBarcodeUrlGenerate a barcode image as a base64 PNG data URL from a value. Use it as an <img> source.
getSelectedRecords
getSelectedRecordsFlatten a list of selection entries (selections or all_records) to their record fields, with quantity merged in. Optional args category, then bucket filter by metadata (omit to return everything).
getRecordsWithQuantity
getRecordsWithQuantityIdentical output to getSelectedRecords (record fields + quantity); intended to be piped from all_records to list every record with its quantity. Optional category / bucket args.
filterAvailableActions
filterAvailableActionsFilter an available_actions array by optional category and/or lever (entries must match every provided dimension). No args → returned unchanged.
5. Choosing the right list
Show what the user selected (reacts to the selection)
selections | getSelectedRecords
Show all records, selected or not
all_records | getRecordsWithQuantity (or available_actions)
Need resolved label / tags / score per record
available_actions (.formatted.*)
Need the raw cube fields
.record / .original (underscore-keyed)
Need the selected quantity
any of the above — quantity is included on selections / all_records (and merged by getSelectedRecords / getRecordsWithQuantity)
recordis always available.selections,all_recordsandavailable_actionsare populated when the document carries a data layer (templates created from a subscription or fanOut template).
6. Worked example
Last updated
Was this helpful?
