Audience: Contributor
Contract for IValue on element props — literals, expressions, and responsive overrides.
See also: Models · Page structure · Datasets
type IValue = {
raw?: unknown;
expr?: EvalExpressionInput;
interval?: number;
};
| Mode | Example | When to use |
|---|---|---|
| Literal | { "raw": "Hello" } |
Fixed copy, enums, colors, booleans, numbers |
| Expression | { "expr": "state.data.greek.name" } |
Bind to runtime state |
| Empty | omitted prop, or {} |
Treated as unset (ValueOps.isEmpty) |
raw or expr.interval is only meaningful with expr (refresh hints where supported).catalogElementToInstance).PropType = 'attr' | 'css' | 'url' | 'none' (prop-definition.model.ts):
IProp.type |
Effect |
|---|---|
attr |
Host attribute / Ionic property |
css |
Style contribution (name often = CSS property; may use resultExpr) |
url |
Bound URL |
none |
Logical / non-rendered (e.g. blockId on lkt-block) |
PropDefinitionOps.cssPropertyName: prop name background-gradient renders as CSS background-image.
Instance props kept by insert: name, type, value, fallback, variance, resultExpr only — not responsive, group metadata, or option bags. Root validators are not copied by catalogElementToInstance (validators nested under children from children.json still arrive via children).
Hard rule (PropDefinitionOps.isBreakpointResponsiveProp): only when type === 'css' or prop name is class or style.
{
"name": "padding",
"type": "css",
"value": { "raw": "8px" },
"responsive": {
"tablet": { "value": { "raw": "16px" } },
"desktop": { "value": { "raw": "24px" } }
}
}
value = mobile.tablet / desktop overrides.resultExprSome props store an editor-friendly value and compute the rendered CSS/attr via resultExpr. Prefer shared layout props under prop/layout/ that already define it.
State.evalScope() is exposed as state inside evalExpression (common/utils). Documented roots:
| Path | Meaning |
|---|---|
state.data.* |
Element / list row data (e.g. for-each source bag) |
state.app.* |
Shared app-session bag |
state.event |
DOM / action payload while an action chain runs |
state.page.params |
Page query / route params |
state.index |
Child index in a repeated template |
There is no item or record root. For lkt-for-each with "source": "greek", bind like state.data.greek.name (see lokakrt/for-each/children.json).
Helpers are injected alongside eval (e.g. URL helpers on the state object) — copy working expressions from pages rather than inventing paths.
Example:
{
"type": "text",
"props": [
{ "name": "html", "value": { "expr": "state.data.greek.name" } }
]
}
Data sources and datasets: Datasets · Data sources.
| Mistake | Fix |
|---|---|
String child instead of text + html |
Always use a text node |
Both raw and expr set |
Keep one |
item.* / record.* expressions |
Use state.data.* / state.app.* / … |
| Persisting empty props from the catalog | Omit them |
| Responsive on non-css/class/style props | Only those names/types support breakpoints |
| Expecting AJV to reject bad bindings | Bindings are not fully schema-enforced |