Reactive templates

Reactive templates

Reactive templates

Add the template parameter to a tag to insert Grid expressions. Each expression participates in the normal dependency graph. Changing an input updates the resulting value without recompiling the model.

input Customer = "Ada"
input Quantity = 2
input UnitPrice = 12
 
Greeting = <raw template>Hello {{Customer}}!</raw>
Order = <json template>
  {"customer": {{Customer}}, "total": {{Quantity * UnitPrice}}}
</json>

raw(template)"Hello {{Customer}}" and triple-quoted tagged strings work too. Ordinary quoted payloads decode Grid string escapes; blocks and triple quotes preserve literal bytes. Existing literals without template keep their current behavior. In particular, <raw>{{Customer}}</raw> remains verbatim text.

Executable Lua tags also use explicit template, with typed scalar operands: <lua type="number" template>return {{Quantity}} * {{UnitPrice}}</lua>. Lua needs no import in a runtime packaged with its engine. See Executable language tags for boundary types and lifecycle.

Choose delimiters

Each format declares its delimiter defaults. Most built-ins use {{ and }}; js uses ${ and }. Imported formats declare defaults in package metadata. Override either delimiter with a start or end attribute when needed:

Greeting = <raw template start="[[" end="]]">Hello [[Customer]]!</raw>

Both delimiters are fixed quoted strings of 1–64 UTF-8 bytes, without control characters. They belong to this template only; they are not runtime cell values. Unicode delimiters are supported. Doubling the opening delimiter emits it literally: {{{{ emits {{, and [[[[ emits [[. The closing delimiter has no special meaning outside a hole. Use distinctive delimiter pairs that do not conflict with the literal's enclosing quote or closing tag.

A hole contains a normal Grid expression. Strings, comments, and balanced expression brackets protect delimiter text inside that expression. Empty or unterminated holes are compilation errors. Source formatting and syntax-tree inspection preserve the delimiter pair and never execute an extension package.

Values and text

The format determines what an insertion means:

Format Whole value or field Inside text
raw and textual tags Text conversion Text conversion
JSON Native value, including arrays and objects Text within a quoted string
YAML and TOML Native value in a scalar position Text within a string
CSV and TSV Native value in a complete data field Text within a field
HTML, XHTML, XML, SVG Text nodes and attribute values Text conversion

Static format structure is parsed during compilation. JSON object keys, table headers, markup tag names, and attribute names must be static. For a dynamic collection, insert an expression that produces that collection into a value slot. This version does not splice markup subtrees, add rows from source text, or accept holes in discarded comments. YAML aliases that duplicate a hole and XML document type declarations are rejected.

Summary = <json template>
  {"count": {{Quantity}}, "label": "Hello {{Customer}}"}
</json>
 
Card = <html template>
  <p title="{{Customer}}">Total: {{Quantity * UnitPrice}}</p>
</html>

Values are inserted into native structure. Serializers own JSON quoting and markup escaping; a customer's name containing <, &, or quotes does not become markup syntax. Formatting a complete document still costs time proportional to its output size.

Additional formats

An explicitly imported extension literal can declare a separate template compiler. It receives static chunks and returns a bounded native construction plan; Grid retains and compiles the expressions. A constant parser alone does not supply template support. See Extension-defined literals.

Specialized representations need their own construction adapter. music, jsx, date/datetime, exact numeric, point, bounding-box and polygon templates currently report that no adapter is installed. When a domain constructor is deliberately desired, use an explicit call with a raw template, for example MUSIC_SCORE(<raw template>{{Notation}}</raw>); that constructor retains its usual runtime cost.

Execution timing

Compilation recognizes delimiters, compiles each Grid expression, parses the static format, validates any extension plan, and lowers construction to normal native expressions. Runtime evaluation reads those dependencies and constructs the value through the single compiled formula evaluator. Structured documents use the existing typed-document carrier, whose materialization and transport cost scale with value size. It does not scan delimiters or invoke the template compiler on first access or on subsequent changes.

Compiled extension templates run without their template package. Recompilation requires that exact package again. Ordinary extension function calls inside a hole still have their own runtime dependency.