Skip to content

HTML State

This example shows one of Ornata’s most useful HTML-first patterns: letting markup provide the initial state.

Open this demo in a new tab

<section
data-counter
data-count="3"
data-label="Server count"
>
<p>
<span data-count-label></span>:
<strong data-count-value></strong>
</p>
<button type="button" data-count-button>Increment</button>
</section>
import { defineComponent } from "ornata";
export const Counter = defineComponent({
name: "Counter",
state: {
count: { default: 0, type: Number },
label: { default: "Clicks", type: String },
},
elements: {
label: { query: "[data-count-label]" },
value: { query: "[data-count-value]" },
button: { query: "[data-count-button]" },
},
methods: {
increment() {
this.state.count += 1;
},
},
render: {
label() {
return {
text: this.state.label,
};
},
value() {
return {
text: String(this.state.count),
};
},
button() {
return {
events: {
click: () => this.methods.increment(),
},
};
},
},
});
Counter.mount("[data-counter]");

The component definition provides defaults:

  • count: 0
  • label: "Clicks"

But the HTML root provides:

  • data-count="3"
  • data-label="Server count"

So the mounted instance starts with:

  • count = 3
  • label = "Server count"

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

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

Now the starting count is 10.