Skip to content

print: placeholder format specifier ({{Price:#,##0.00}}, {{Date:dd.MM.yyyy}}) - #6983

Merged
delchev merged 1 commit into
masterfrom
issue-6982-print-format-specifier
Aug 29, 2026
Merged

print: placeholder format specifier ({{Price:#,##0.00}}, {{Date:dd.MM.yyyy}})#6983
delchev merged 1 commit into
masterfrom
issue-6982-print-format-specifier

Conversation

@delchev

@delchev delchev commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

What

An optional format pattern on a .print placeholder operand, after its first ::

<column width="*" align="right" label="PRICE">{{Price:#,##0.00}}</column>
<text align="right">Date: {{document.Date:dd.MM.yyyy}}</text>
<text>{{At:HH:mm}}</text>                                  <!-- first colon splits -->
<text>{{A:0.00|B:#,##0.00}}</text>                         <!-- per-operand, fallback unchanged -->
  • a Number (any subtype, Long included) formats via DecimalFormat with the existing ROOT + space-grouping symbols
  • a temporal — or the ISO date / date-time string a PrintFeeder emits for one — formats via DateTimeFormatter.ofPattern
  • a pattern the value cannot satisfy, or a value of any other shape, falls back to the default rendering: a printout never shows an exception, per the parser's leniency contract
  • |-fallback semantics unchanged (blankness judged on the rendered result, last operand always renders)

Why

DataBinder.stringify money-formats only Double/Float/BigDecimal, and both print paths (PrintEndpoint, PrintFacade) parse the payload with Gson LONG_OR_DOUBLE — so whether a money value formats is decided by whether the JSON happens to carry a decimal point. The browser path makes that systematic: JSON.stringify(5390.00) emits 5390, which lands as a Long and prints bare next to a formatted totals block, and nothing the template author writes can fix it. Blanket-formatting Long in the binder would be wrong (ids, years), so the knob belongs to the template, mirroring the {date:yyyyMMdd} token the declarative fileName patterns already use (#6904).

Backward compatible: no existing .print template (shipped or generated) carries a : inside a placeholder body, so every template renders byte-identical without the specifier.

Testing

Six new DataBinderTest cases: integral-Long money formatting + grouping, explicit pattern overriding the default money pattern, temporal and ISO-string date reformatting, first-colon split (HH:mm), fallback on an unsatisfiable pattern (string + invalid date pattern), and format combined with | alternatives. Full modules/parsers/document suite green (110 tests).

Fixes #6982

🤖 Generated with Claude Code

….yyyy}})

A .print template had no way to control how a bound value renders.
DataBinder money-formats only Double/Float/BigDecimal, and both print
paths parse the {document, items} JSON with LONG_OR_DOUBLE - so a money
value that lands on a whole figure (the browser strips the trailing .00:
JSON.stringify(5390.00) emits 5390) arrives as a Long and prints bare
next to a formatted totals block. Dates had the sibling problem: an ISO
2026-08-29 could not be reformatted to a local convention.

Blanket-formatting Long in the binder would be wrong (ids, years), so
the knob goes to the template author: an operand may carry a pattern
after its first colon, mirroring the {date:yyyyMMdd} token of the
declarative fileName patterns. A Number (Long included) formats via
DecimalFormat with the existing ROOT + space-grouping symbols; a
temporal - or the ISO string a feeder emits for one - via
DateTimeFormatter. The first colon splits, so time patterns keep their
own colons ({{At:HH:mm}}). A pattern the value cannot satisfy, or a
value of any other shape, falls back to the default rendering - a
printout never shows an exception, per the parser's leniency contract.
|-fallback semantics are unchanged (blankness judged on the rendered
result); no existing template carries a colon in a placeholder body, so
every shipped template renders byte-identical.

Fixes #6982

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@delchev
delchev merged commit 613bf8c into master Aug 29, 2026
10 checks passed
@delchev
delchev deleted the issue-6982-print-format-specifier branch August 29, 2026 10:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

print: placeholder format specifier - whole-number money values print bare (5390, not 5 390.00)

1 participant