Skip to main content
Sprincul is designed around a single explicit initialization call. When you call Sprincul.init(), it scans the DOM for every [data-model] element present at that moment, wires up bindings and event handlers, and runs the lifecycle hooks. Any data-model elements you add to the DOM afterward are not processed automatically.

Why Sprincul does not auto-observe

Scanning the DOM continuously for new elements means running hidden work on every mutation — work that may conflict with how your own code manages the DOM. Keeping initialization explicit makes it easier to predict exactly when models start up and avoids surprise re-initialization in apps that already control their own DOM lifecycle. If you do need to initialize models in markup injected after the first init() call, you can add that behavior yourself with a short amount of code.

The manual reinit pattern

The pattern has three steps: observe the DOM for your injected containers, register any onReady callbacks you need for that cycle, then call Sprincul.init() again. Sprincul skips elements it has already initialized, so only the newly added roots are processed.
1

Add a MutationObserver in your own code

Set up the observer before or after calling Sprincul.init(). Watch the parent element where you plan to inject new model markup.
2

Register onReady callbacks for the new cycle

onReady callbacks are consumed once per init() call. If you want a callback to run after the next init, register it fresh before calling Sprincul.init() again.
3

Inject your markup and let the observer trigger reinit

When you insert new HTML containing data-model elements, the observer fires, which calls reinitialize(), which processes only the new roots.

Complete example

Cloaking still works in subsequent init calls

If you add data-cloaked to your injected model markup, cloaking behaves exactly the same as on the first pass. Model-level cloaking waits for afterInit() to complete before revealing the element, which is especially useful when each card needs to fetch its own data after mounting.

Already-initialized roots are skipped

Sprincul tracks which elements it has processed using a WeakSet. When you call Sprincul.init() again, it queries the full document for [data-model] elements but skips any it has already seen. You do not need to scope the second call or pass a container reference — the framework handles deduplication internally.
For more context on what Sprincul does and does not track across DOM changes, see the Limitations & FAQ page.