Skip to content

Instance Management

Once a component is mounted with mount() or mountAll(), the resulting instance becomes the main point of direct interaction. It can be stored, referenced, and manipulated as needed.

Both mounting APIs return the mounted instance directly. This is the simplest way to work with an instance when you already have access to it in the same scope.

const one = Counter.mount('[data-counter]');
const many = mountAll({
Counter,
Disclosure,
});

Every component constructor provides methods for retrieving an already mounted component instance. This is useful when you need to access an instance from a different scope than the one where it was originally created. The instance is identified by a direct reference to, or a query selector for, its root element.

Use getInstance() when you expect the instance to exist and want its absence to throw.

const instance = Counter.getInstance('[data-counter]');

Use findInstance() when the instance may or may not exist.

const maybeInstance = Counter.findInstance('[data-counter]');
if (maybeInstance) {
maybeInstance.state.count += 1;
}

Once you have access to an instance, it becomes the main way to interact with the component from surrounding code.

The public instance exposes:

  • root: Access the resolved element the component was mounted on.
  • state: Read and mutate the public reactive state object.
  • dispose(): Subscribe to public state changes from outside code.
  • addStateListener(): Tear down the component instance and free up memory.

One of the main reasons to work with a mounted instance is access to its public state.

The instance’s state object exposes the component’s public reactive state from outside the component. This allows surrounding code to read current values and, when appropriate, update them directly.

const instance = Counter.mount('[data-counter]');
console.log(instance.state.count);
instance.state.count += 1;

When public state is updated successfully, Ornata runs the normal update flow for that component.

Use addStateListener() to subscribe to changes for a specific public state property on a mounted instance. This enables surrounding code to react to state changes without owning the state update itself.

const instance = Counter.mount('[data-counter]');
const cleanup = instance.addStateListener('count', (event) => {
console.log(event.newValue);
});

This is useful when page code needs to observe component behavior from the outside, such as syncing another part of the interface, triggering related logic, or responding to state updates across component boundaries.

The returned cleanup() function can be used to remove the listener when it is no longer needed.

When a component is no longer needed, it can be unmounted in a few different ways.

When you know the root, you can unmount from the constructor:

Counter.unmount('[data-counter]');

When you need to tear down every mounted instance for the same component constructor, use unmountAll().

This is especially useful for test cleanup or page-level teardown.

Counter.unmountAll();

When you already have the instance reference, you can dispose of it directly:

const instance = Counter.mount('[data-counter]');
instance.dispose();

Note: Tearing down an instance automatically unbinds all internal DOM events and cleans up any active state listeners created by addStateListener().

  • getInstance() retrieves an existing one and throws if missing
  • findInstance() retrieves an existing one or returns null
  • state lets you read and update public state
  • addStateListener() lets outside code observe public state changes
  • unmount() removes an instance by root
  • unmountAll() removes every mounted instance for that constructor
  • dispose() removes the current instance directly