Skip to content

State

State is one of the core building blocks in Ornata.

It is designed to work well with HTML-first markup, progressive enhancement, and direct component updates.

Ornata can build a component’s initial state from:

  • default values in the component definition
  • data-* values on the root HTML element
  • initialState passed to mount()

That makes state flexible in an HTML-first environment because a server template, CMS, or other markup source can provide initial values while JavaScript still refines or overrides them at mount time.

When Ornata resolves initial state, later sources win.

The current order is:

  1. component default values
  2. parsed values from the root element dataset
  3. initialState passed to mount()

That means mount-time JavaScript wins over HTML, and HTML wins over definition defaults.

<section
data-counter
data-count="5"
data-label="Server count"
></section>
const Counter = defineComponent({
state: {
count: { default: 0, type: Number },
label: { default: "Clicks", type: String },
},
});
Counter.mount("[data-counter]");

The mounted instance starts with:

  • count = 5
  • label = "Server count"
Counter.mount("[data-counter]", {
count: 10,
});

Now count starts at 10, even if the HTML contained data-count="5".

When state changes after mount, Ornata runs its update flow automatically.

That includes:

  • validating the new value
  • recomputing computed values
  • re-running render callbacks
  • calling matching watch callbacks
  • notifying external state listeners

This means state updates drive the component directly.

methods: {
increment() {
this.state.count += 1;
},
}

You do not need a separate setter API to trigger updates. Updating the state property is the update.

Ornata gives you two different ways to react to state changes:

  • watch for internal component-side reactions
  • addStateListener() for external subscriptions on a mounted instance

Use watch when the component itself needs to respond to its own updates.

Use addStateListener() when code outside the component needs to observe public state changes.

Read Watchers and State Listeners for the deeper guidance.

Ornata also protects state access at the component boundary.

Each state property can define:

  • type
  • parse
  • private
  • readonly
state: {
count: { default: 0, type: Number },
token: { private: true },
label: { default: "Clicks", readonly: true },
}

These options support a few useful guarantees:

  • invalid values can be reported
  • HTML dataset values can be parsed into the expected type
  • private state cannot be read or written externally
  • readonly state cannot be written externally

When state is read from HTML, Ornata uses the state property options to decide how to parse the value.

Depending on the configuration, it can parse:

  • strings
  • numbers
  • booleans
  • arrays
  • objects

You can also supply parse() when you want custom parsing logic.

state: {
filters: {
parse(value) {
return value.split(",");
},
},
}

Ornata state is:

  • flexible at initialization time
  • direct to update
  • reactive once mounted
  • guarded at the public boundary

That makes it a strong fit for HTML-first environments that need interactive behavior without giving up control over where the initial data comes from.

State is not the only place to keep values

Section titled “State is not the only place to keep values”

If a value should persist for the life of the component instance but should not be reactive, use data instead.

Read Data for that pattern.