Skip to main content
Sprincul’s entire HTML surface is four kinds of attribute. You mark container elements with data-model, wire state updates to elements with data-bind-*, hide content until initialization with data-cloaked, and attach event handlers with native on<event> attributes. Sprincul reads these at init() time and does not require any special template syntax or build step.

data-model="<Name>"

Marks an element as the root of a model instance. Sprincul looks for all [data-model] elements in the document when Sprincul.init() runs and creates one model instance per element. The value must exactly match a name you passed to Sprincul.register() or Sprincul.registerAll() — casing is significant. Every data-bind-* and on<event> attribute inside this container is scoped to this model instance.
You can use any block-level or sectioning element as the root:
Nesting one data-model container inside another is allowed — each creates its own independent model instance. Bindings and events on an inner container are scoped to the inner model only.

data-bind-<prop>="<callback>"

Registers a reactive binding between a state property and a DOM element. When this.state.<prop> changes on the model, Sprincul calls <callback>(element) so your method can update that element directly. You decide exactly what “update” means — set textContent, change a class, update a value, anything. <prop> is the lowercase state property name. <callback> is the name of a method on your model class that accepts an HTMLElement as its first argument.
You can bind multiple elements to the same state property, and you can bind multiple different properties within the same model:
State property names used in data-bind-* attributes must be lowercase. Browsers lower-case data-* attribute names when parsing HTML, so data-bind-myProp becomes data-bind-myprop in the DOM. If your state key is myProp and your attribute is data-bind-myProp, the binding will never fire. Use this.state.myprop and data-bind-myprop consistently.

data-cloaked

Hides an element until Sprincul removes the attribute at the appropriate point in the initialization cycle. You provide the CSS rule that makes the hiding work — Sprincul only removes the attribute.
The behavior differs depending on where you place the attribute: On a data-model element — Sprincul removes data-cloaked after that model’s afterInit hook completes, including any async work. Use this for models that fetch data before displaying anything.
On the <body> element (or any element without data-model) — Sprincul removes data-cloaked immediately after all models’ afterInit hooks are called, without waiting for them to complete. Use this for a simple page-level fade-in when you don’t need to wait for async hooks.
You can combine both strategies. Model-level cloaking protects individual components that do heavy async work, while page-level cloaking prevents unstyled flashes across the rest of the page:
For models that make API calls in afterInit, prefer model-level cloaking. It prevents users from briefly seeing placeholder or default state values before real data arrives.

on<event>="<methodName>"

Attaches a native DOM event listener to an element. The value is the name of a method on your model class — not inline JavaScript. Sprincul replaces the attribute with a proper addEventListener call and passes the native Event object to your handler. Common examples: onclick, oninput, onchange, onsubmit, onkeydown. Any valid DOM event name works as long as you prefix it with on.
For input and form events, your handler receives the native event object:
Sprincul removes the on<event> attribute from the DOM after wiring the listener, so the raw attribute value is never exposed as executable HTML. Your handler name is private to the model instance.