# Data Binding Macros — Print Layout V2

Print layout macros use `{{ }}` double-brace syntax. They resolve at render time from the
`<Declarations>` block or the framework's `Labels` registry. A typo or missing Declaration
causes the literal `{{...}}` text to appear in the rendered document.

---

## Declaration Property Access

### Direct property

```xml
{{Declarations::<varName>.<propertyName>}}
```

Read a single scalar property from a declared BO or LU.

Examples (from `OrderConfirmationPDF.printlayoutv2.xml`):

```xml
{{Declarations::order.orderId}}
{{Declarations::order.deliveryDate; dateTimeFormat=date}}
{{Declarations::salesOrg.text}}
{{Declarations::salesOrg.phone1}}
{{Declarations::order.currency}}
```

### Nested object property (LU nested in BO)

```xml
{{Declarations::order.luDeliveryRecipient.name}}
{{Declarations::order.luDeliveryRecipient.street}}
{{Declarations::order.luResponsible.name}}
```

Navigates through a sub-object (nested LU) on the declared BO. Observed in
`OrderConfirmationPDF.printlayoutv2.xml` and `DirectCashInvoicePDF.printlayoutv2.xml`.

### Entire declaration reference (image/signature)

```xml
<img src="{{Declarations::myImageName}}" width="100" />
<img src="{{Declarations::signature1}}" width="160" alignment="left" />
```

For `Image` and `Signature` declarations the macro resolves to the binary content directly.
Used in the logo and signature table rows of all Order print layouts.

---

## Current Item Access (inside `<each>`)

Inside an `<each>` block, reference the current row's fields with dot-only notation:

```xml
{{.fieldName}}
{{.price; numberFormat=8.2}}
{{.status; toggleId=DomStatus; toggleField=shortText}}
```

You cannot use `{{Declarations::...}}` to reference the iteration item — use `{{.fieldName}}`.

---

## Labels

Localized text with a fallback default:

```xml
{{Labels::<labelId>; defaultLabel=<fallbackText>}}
```

Examples:

```xml
{{Labels::AddressId; defaultLabel=Address:}}
{{Labels::DocumentNoId; defaultLabel=Document No.:}}
{{Labels::TotalId; defaultLabel=Total}}
{{Labels::OderConfirmationId; defaultLabel=Order Confirmation}}
```

-   `<labelId>` — the i18n key registered in the label resource (must be unique)
-   `defaultLabel=` — displayed when the key is not found in the active locale
-   **Always set a non-empty `defaultLabel`** — without it, the label renders as the raw id string

---

## Formatters (modifier syntax)

Formatters appear after a semicolon inside the macro:

```xml
{{Declarations::order.deliveryDate; dateTimeFormat=date}}
{{.quantity; numberFormat=8.2}}
{{.basePriceReceipt; numberFormat=8.2}}
{{.grossValueReceipt; numberFormat=8.2}}
{{.taxClassification; toggleId=DomTaxClassification; toggleField=shortText}}
```

| Formatter                  | Syntax                                   | Purpose                                                   |
| -------------------------- | ---------------------------------------- | --------------------------------------------------------- |
| `numberFormat`             | `numberFormat=8.2`                       | Numeric display: `8` = total digits, `2` = decimal places |
| `dateTimeFormat`           | `dateTimeFormat=date`                    | Format as date string per device locale                   |
| `toggleId` / `toggleField` | `toggleId=DomXxx; toggleField=shortText` | Resolve domain enum value to display text                 |

Multiple formatters can be combined: `{{.value; numberFormat=8.2}}` is most common.

---

## `path=` Prefix

Used inside correlation sub-rows to disambiguate item path:

```xml
{{path=.text1}}
```

Observed in `OrderConfirmationPDF.printlayoutv2.xml` correlation rows alongside regular `{{.fieldName}}`.
Use when the field could be ambiguous in a nested context.

---

## Image Embedding

```xml
<img src="{{Declarations::myImageName}}" width="100" />
```

The `DataDeclaration` for the image must specify:

```xml
<DataDeclaration name="myImageName" type="Image" mimeType="image/png" imageId="CompanyLogo" />
```

-   `imageId` must match a file registered in `src/Images/` (e.g., `CompanyLogo`)
-   `<img>` must declare `width`
-   `<img>` cannot appear inside a `<td>` — place it in a `<td>` that contains only the `<img>` via `rowSpan`

Signature images follow the same pattern but use `type="Signature"`:

```xml
<DataDeclaration name="signature1" type="Signature" />
<img src="{{Declarations::signature1}}" width="160" alignment="left" />
```

---

## PRINTV2 Process Action — Binding Declarations to ProcessContext

The caller process maps ProcessContext variables to Declaration names:

```xml
<Action name="PrintDocument" actionType="PRINTV2"
        printId="ProcessContext::PrintId"
        locale="ApplicationContext::user.languageSpoken">
  <Parameters>
    <Input name="order"      value="ProcessContext::MainBO" />
    <Input name="salesOrg"   value="ApplicationContext::SalesOrg" />
    <Input name="signature1" value="ProcessContext::TextItems.signature1MediaPath" />
  </Parameters>
  <Return name="ProcessContext::FinalPath" />
  <TransitionTo action="AfterPrint" />
</Action>
```

The `<Input name="order">` name must match a `<DataDeclaration name="order">` exactly.

---

## Common Mistakes

| Mistake                        | Symptom                                   | Fix                                                      |
| ------------------------------ | ----------------------------------------- | -------------------------------------------------------- |
| Typo in declaration name       | Literal `{{Declarations::...}}` in output | Match `DataDeclaration name=` exactly                    |
| Missing `defaultLabel=`        | Raw label id in output                    | Add `defaultLabel=<text>` to every `{{Labels::...}}`     |
| Wrong path depth               | Empty cell                                | Verify BO property names in the SQLite schema            |
| `<img>` inside `<td>`          | Build or render error                     | Move `<img>` outside `<td>` or use `rowSpan` on the cell |
| `imageId` not in `src/Images/` | Blank image in output                     | Verify the image asset exists before referencing it      |
