declare the component's state (JSON; may reference globals like a baked DP_INIT)
data-bind:field
two-way bind a control's value to a signal
data-text="expr"
element text content
data-show="expr"
toggle visibility (inline display)
data-class:name="expr"
toggle a class
data-attr:name="expr"
toggle/set an attribute (see boolean rule below)
data-style:--prop="expr"
drive a CSS custom property → repaints through the engine
data-on:evt="stmt"
event handler (click, input, keydown, focus, blur, …); evt is in scope
Gotchas (all verified by rendering)
Lowercase the signal namespace. HTML lowercases attribute names, so
data-signals:calSm becomes calsm and $calSm silently fails to resolve.
Use all-lowercase namespaces: dp, rng, cb, sel, view, cal.
data-attr:NAME with a boolean toggles attribute presence, not a
"true"/"false" string. data-attr:data-ui-selected="cellIso(v,i) === $cal.sel"
puts data-ui-selected on the selected cell and removes it elsewhere — so
[data-ui-selected] matches exactly. Multi-dash names work. For a token
attribute (a value, not mere presence) use a ternary:
data-attr:aria-current="cellIsToday(v,i) ? 'date' : 'false'" → matched as
[aria-current="date"].
data-style:--prop is the reactive paint knob — for COMPONENT CHROME
only.data-style:--bg="busy(iso)" drives a cell's surface through the
color engine; prefer it over toggling many classes. It is NEVER for
application data or chart marks — data recolors server-side (the
svg-charts backend-toggle rule); this knob paints the throwaway
interaction state a component owns.
Avoid data-computed. It silently no-opped under an earlier bundle;
inline the expression in each binding instead. (The project pins Datastar Pro
v1.0.2, which does export computed — re-verify by rendering before relying
on it.)
No client loops. Bake the constant DOM, then data-show/data-text each
baked node. Don't try to generate rows on the client.
A suggest lane replies to a FIXED listbox id.SuggestReply(w, r, "ws", …) patches #ws-list (ComboOptionsView renders id+"-list"),
so a ComboBox/ComboSelect's id must EQUAL its lane's reply id and be
unique on the page. gf-367: the portfolio wizard's pfws/pfwb boxes
posted to lanes that answered ws/wb — the search never landed an
option and nobody saw an error.
data-bind takes the VALUE form here: data-bind="sq", never the
key form data-bind:sq (gf-385: the group-pick input rendered
data-bind:gpq and neither direction synced — the pick wrote the
signal and the field kept the typed text; the pinned bundle honours
the value form, which every combobox uses).
Load Datastar from /static/datastar.js (the pinned Pro bundle,
v1.0.2) as a <script type="module"> — the base layout does this once;
never add a second runtime or a CDN copy. (Inlining is only for throwaway
offline artifacts, not this app.)