Layout Element Values¶
Textual Elements¶
Textual elements (TEXT, TABLE) have options to control how the text appears: size, font, spacing, positioning, etc.
Text Formatting¶
Textual elements can control font size, font family, and paragraph spacing.
paragraphFontSizecontrols the font size. Default is6.paragraphSpacingcontrols the paragraph spacing. Default is6. The font size cannot exceed the spacing.paragraphFontNamecontrols the font family. Supported fonts:- Times-Roman
- Times-Bold
- Times-Italic
- Times-BoldItalic
- Helvetica (default)
- Helvetica-Bold
- Helvetica-Oblique
- Helvetica-BoldOblique
- Courier
- Courier-Bold
- Courier-Oblique
- Courier-BoldOblique
- Symbol
- ZapfDingbats
Text Alignment¶
Textual elements can control how text is aligned inside the element boundaries, or, in the case of tables, inside each cell.
horizontalParagraphAlignmentcontrols horizontal alignment:LEFT,CENTER(default),RIGHTverticalParagraphAlignmentcontrols vertical alignment:TOP,CENTER(default),BOTTOM
Responsive Sizing¶
Textual elements also allow you to specify how the text behaves when it overflows the layout element boundaries, using paragraphTextResizeStrategy:
ALLOW_OVERFLOW(default) displays text at its initial font size, even if it overflows the layout element boundaries.TRUNCATE_TEXTpreserves the initial font size and removes letters from the end until the remaining text fits. An ellipsis (...) is appended to indicate truncation.SHRINK_TEXTpreserves the initial text length but progressively reduces the font size until the text fits.
Note: TRUNCATE_TEXT and SHRINK_TEXT are best-effort; they will only shorten or shrink the text to a certain point before giving up.
Element Values¶
A value is the data that appears inside a layout element: paragraph text, table contents, image data, or barcode contents. This data is produced by a value template.
Value Templates¶
The value template is a string used to specify text, HTML, or images that will appear inside the element. Different element types use the value template differently, and some do not use it at all.
Each value template is processed before being rendered onto the label.
Template Processing¶
All value templates are processed with Jinja before being added to the label.
TEXTuses the processed value as the text displayed inside the element.- Example:
Hello, my name is {{ user.name }}
- Example:
TABLEuses the processed value as the HTML table displayed inside the element.- Example:
<table><tr><td><b>First Name</b></td><td><b>Last Name</b></td></tr><tr><td>{{ user.firstName }}</td><td>{{ user.lastName }}</td></tr></table>
- Example:
IMAGEuses the processed value as a reference to a base64-encoded image.CODE128_BARCODE/CODE39_BARCODEuse the processed value as the barcode's scan value.QR_CODEuses the processed value as the QR code's scan value.BOXdoes not use a value template.
Jinja Templating¶
Value templates use Jinja syntax. The most important feature is variable interpolation with double curly braces:
When the label PDF is generated, T3 processes each value template against the data available for that label. Variables are drawn from these namespaces:
- Per-label data: each entry in your data list. For example, if your data list contains
{"package": {"label": "1A44..."}}, then{{ package.label }}renders1A44.... - Shared data: values passed via
commonContentDataare merged into the top level of every label's data, so acommonContentDataof{"facilityContactInfo": {...}}is read as{{ facilityContactInfo.phoneNumber }}, not{{ common.facilityContactInfo.phoneNumber }}. A key you set per label wins over the shared value of the same name. images.*: base64 image data you supplied, accessed by filename. For example,{{ images['logo.png'] }}.t3.*: built-in text and images provided by T3. For example,{{ t3.images['t3_logo.png'] }}or{{ t3.text.poison_control_center_phone }}. CallGET /v2/labels/globalsfor the full list.data.*: an alias for that label's entire data entry, so{{ data.package.label }}and{{ package.label }}are equivalent. Useful when a key name would otherwise be ambiguous.
Jinja also supports conditionals, loops, and filters, which can be useful for labels that conditionally display information:
Filters¶
Jinja filters transform a value on its way onto the label, written with a pipe: {{ value | filterName }}. All of Jinja's built-in filters are available, including upper, title, round, truncate and default.
T3 adds three of its own, for things a template cannot do on its own.
boldEndingDigits¶
Bolds the significant tail of a Metrc tag, so the part that differs between packages is the part that reads at arm's length.
A tag of 1A4400005678000000000001 renders as 1A4400005678000000000001. The filter takes the last 8 characters, finds the first one that is not a zero, and wraps that character and everything after it in <b>. Apply it to a tag string, not to the package.
packageStateName¶
Resolves the state a package belongs to, from the Metrc hostname it was loaded from.
A package from ca.metrc.com renders as California. Apply it to the package itself rather than to a field. A hostname T3 does not recognize falls back to its prefix, uppercased, so an unmapped xx.metrc.com renders as XX.
This is worth knowing about because the state is not a field on the package. It is carried by the hostname, so there is no package.state to read.
strict¶
Turns a single value that would render blank into an error.
Use it on the one or two fields that must never print empty, while leaving the rest of the label forgiving. For the same behaviour across every expression at once, use strictTemplates in your rendering options instead, described under Catching Blank Output While Authoring.
Missing Values¶
By default, an expression that cannot be resolved renders as an empty string rather than failing. {{ package.lot }} on a package with no lot key simply prints nothing.
That is forgiving when a field is genuinely optional, but it also means a typo produces a silently blank label. To supply an explicit fallback:
default only covers keys that are missing. To also cover keys that are present but null, pass true as a second argument:
To guard an optional key in a conditional, prefer is defined over a bare truthiness test:
Missing Images¶
IMAGE elements are the one exception to the blank-by-default rule above. An image has nothing to draw when its value template resolves to nothing, so blank output is reported as a 400 LABEL_TEMPLATE_ERROR instead of printing an empty rectangle.
This most often happens when the filename in the template does not match the one in your images payload:
payload = {
"images": {"logo.jpg": "data:image/png;base64,iVBORw0KGgoAAA..."},
"labelContentLayoutConfig": {
"labelContentLayoutElements": [
{"elementType": "IMAGE", "description": "Brand logo",
"valueTemplate": "{{ images['logo.png'] }}"}
]
},
# ...
}
logo.png was never supplied, so the response names the element and the key you probably meant:
{
"code": "LABEL_TEMPLATE_ERROR",
"detail": "1 template problem across 40 labels. element[0] 'Brand logo' (IMAGE) line 1 — 'dict object' has no attribute 'logo.png' — that object has 1 key(s): logo.jpg",
"errors": [
{
"elementIndex": 0,
"elementType": "IMAGE",
"description": "Brand logo",
"line": 1,
"sourceLine": "{{ images['logo.png'] }}",
"didYouMean": ["logo.jpg"],
"occurrences": 40,
"firstLabelIndex": 0
}
]
}
The same error covers image data that is present but unusable; a payload that is not valid base64, or base64 that does not decode to a PNG, JPEG or GIF.
If an image is genuinely optional, give the template something to fall back on rather than letting it render blank:
To drop the image from a layout entirely, set enabled to false on the element.
Catching Blank Output While Authoring¶
Set strictTemplates in your rendering options to turn every silently-blank expression into an error:
With strictTemplates enabled, an undefined variable, a missing key, or a null value all return a 400 LABEL_TEMPLATE_ERROR naming the element, the line, and what the data actually held. The default filter and is defined shown above continue to work, so they remain the way to say "blank here is intentional."
It defaults to false, so existing layouts are unaffected. Turning it on while building a layout is the fastest way to find typos; leaving it off in production keeps optional fields forgiving.
If a template fails, T3 returns a 400 Bad Request reporting every problem it found across your layout and data, not just the first. See Troubleshooting in the tutorial.
Next Steps¶
- Back to the element reference: Label Layouts.
- Where the values come from: Label Data.
- Work through a data-driven label in Name the Product.