# Units: Formatter

> Derived values from other paths.

Glider documentation · Logic · Web page: https://cgglider.com/docs/units/formatter/

Sections of this page: [Overview](https://cgglider.com/docs/units.md) · [Clock](https://cgglider.com/docs/units/clock.md) · [Counter](https://cgglider.com/docs/units/counter.md) · [Ticker](https://cgglider.com/docs/units/ticker.md) · [Formatter](https://cgglider.com/docs/units/formatter.md) · [Watch rule](https://cgglider.com/docs/units/watch-rule.md) · [Data feed](https://cgglider.com/docs/units/poller.md) · [Runtime & gating](https://cgglider.com/docs/units/runtime.md) · [Commands & API](https://cgglider.com/docs/units/commands.md)

A formatter reads named inputs and calculates one or more outputs. It evaluates once on load and whenever any input changes. Use it for calculated values and text; use a Watch rule when a particular source change must pass a condition before writing.

| Field | Meaning |
| --- | --- |
| Inputs → Keys | Names used in expressions: in1, in2, … by default, or your own names such as home and away. The narrower left column holds the name. |
| Inputs → Values | The source path to read for that name: data:: for page data, poller::<feed>:: for a feed field, or sheets:: for a spreadsheet. The = sign connects the name with its source. |
| Outputs → Keys | The destination path to write. Add output creates another assignment in the same formatter. |
| Outputs → Values | An input name or an expression, such as home + away. Quote fixed text: "Hello". Text with values in it can use a template string: `${home} - ${away}`. Ctrl-Space lists suggestions. |
| Process → On missing | Compact settings above the tables: hold (keep the last value), blank, zero, or fallback. Applies to every output when an input is missing/null/NaN, or to an output whose result is missing/null/NaN. |
| Process → Fallback | The replacement text, shown beside On missing when fallback is selected. |

Drag the grip at the left of an input or output row to change its order. The key and value move together, and the order is saved with the page. With the grip focused, Alt + ↑ / ↓ moves a row from the keyboard. At least one complete output is required; a new output stays a draft until its path and expression are filled.

For a single-tab spreadsheet, select the sheet once and then a cell. The field shows its name, for example sheets::MLBB SHEET.A1; the extra tab key and technical sheet ID are hidden. Multi-tab files list file / tab together. Renaming a sheet updates its displayed name while the saved binding keeps its stable identity. Long addresses scroll with the caret as you move through them.

> **Writable destinations:** Outputs can write page-data paths or single spreadsheet cells. Cell writes appear in the grid, recalculate dependent formulas and are saved with the page. Feed fields and whole spreadsheet columns are read-only. Every output is checked for writer conflicts, invalid expressions and reading its own output.

## Multiple outputs in a config

```json
{
  "inputs": {
    "home": "data::score.home",
    "away": "data::score.away"
  },
  "outputs": [
    {
      "output": "data::score.total",
      "expr": "home + away"
    },
    {
      "output": "data::score.label",
      "expr": "`${home} - ${away}`"
    }
  ],
  "onMissing": "hold"
}
```

Existing single-output configs with expr and output still work. For multiple outputs, use the ordered outputs array; expr and output mirror its first row. The evaluate action recalculates all outputs, and clear blanks all output destinations.

> **Two checks bite here:** An expression that references an undeclared name or a non-whitelisted function is rejected (expr). So is a formatter whose input reads its own output path — “reads its own output … as input …” — because that is an accumulator, not a derivation.
