Skip to content

HTML State

This example shows one of Ornata’s most useful HTML-first patterns: deriving initial component state from markup. It gives server-rendered data and configuration a direct path into component behavior at runtime.

With the exception of more complex state properties, such as functions, component state can be initialized from corresponding data-* attributes on the component’s root element. In this example, the server provides a count value in the HTML, which the Ornata component reads during initialization and uses as the starting point for its state.

Open this demo in a new tab

<!-- 👇 The server-provided state is applied directly to the root element -->
<section data-counter data-count="3">
<p>
<span>Server count:</span>
<strong data-count-value></strong>
</p>
<button data-count-button>Increment</button>
</section>
import { defineComponent } from 'ornata';
export const Counter = defineComponent({
name: 'Counter',
state: {
count: { default: 0, type: Number },
},
elements: {
value: { query: '[data-count-value]' },
button: { query: '[data-count-button]' },
},
methods: {
increment() {
this.state.count += 1;
},
},
render: {
value() {
return {
text: String(this.state.count),
};
},
button() {
return {
attributes: {
type: 'button',
},
events: {
click: () => this.methods.increment(),
},
};
},
},
});
Counter.mount('[data-counter]');

The component definition provides defaults:

  • count: 0

But the HTML root provides:

  • data-count="3"

So the mounted instance starts with:

  • count = 3

If you mount with initialState, that wins over the HTML values:

Counter.mount('[data-counter]', {
count: 10,
});

Now the starting count would be 10 instead of 3.