Sprincul.init() runs. Understanding this sequence tells you exactly when your state, bindings, and async operations are active — and which hook is the right place for each kind of work.
The initialization flow
When you callSprincul.init(), Sprincul queries the DOM for every element with a data-model attribute and processes each one in order:
Sprincul.init() scans the DOM
Sprincul finds all
[data-model] elements and looks up the registered class for each one.Model instance is created
Sprincul calls
new YourModel(element), which sets up this.$el and the reactive this.state proxy.beforeInit() is called
Sprincul calls
beforeInit() synchronously. This is where you initialize state values and register computed properties — before any bindings exist.Bindings and event listeners are attached
Sprincul reads every
data-bind-* and on<event> attribute in the container and wires them to your model’s methods. Each binding callback is called once immediately with the current state.afterInit() is called
Sprincul calls
afterInit(). Bindings are already active at this point, so any state changes here will trigger DOM updates. afterInit() can be async.beforeInit()
beforeInit() runs synchronously before Sprincul attaches any bindings to the DOM. Use it to:
- Set initial values on
this.state - Register computed properties with
this.addComputedProp() - Run any synchronous setup that must complete before bindings are active
beforeInit() is called synchronously, but it can return a Promise. If it does, Sprincul will not await it — bindings are set up immediately after beforeInit() returns. Keep synchronous work in beforeInit() and defer async work to afterInit().afterInit()
afterInit() runs after bindings are fully active. Use it to:
- Fetch data from an API and update
this.state - Connect to an external store or pub/sub system
- Start timers or observers that rely on the DOM being ready
afterInit() can be async. Sprincul does not block the rest of initialization while it completes — it calls afterInit(), captures the returned promise, and moves on to the next model. When the promise settles, Sprincul removes data-cloaked from the model’s root element if present.
Sprincul.onReady(callback)
Register a callback to be notified when all models have been initialized. The callback receives an array of SprinculModelInfo objects, one per model instance Sprincul processed.
The sprincul:ready DOM event
As an alternative to onReady, you can listen for the sprincul:ready CustomEvent on the document. It fires at the same time as onReady callbacks and carries the same model information in event.detail.models.
Development mode
Pass{ devMode: true } to Sprincul.init() to enable additional diagnostics:
- Console warnings when bindings reference callbacks that don’t exist on the model.
- Console warnings when event attributes reference methods that don’t exist on the model.
- The
instanceproperty on eachSprinculModelInfoobject, giving you direct access to the model instance inonReadycallbacks and thesprincul:readyevent.
Cloaking elements during initialization
Sprincul supports adata-cloaked attribute that hides elements until they are ready. You provide the CSS rule; Sprincul removes the attribute at the right time.
afterInit() to fully resolve, making it safe for models that fetch data before rendering. Page-level cloaking removes as soon as all afterInit() calls are dispatched — not when they complete — so it is better suited for showing a loading state than for waiting on async work.