A first component¶
Components that are not pages are declared with @component alone. This counter keeps its
state in a reactive property and re-renders only the paragraph that displays it:
src/app/components/counterButton.ts
import { CustomElement, component, html, react } from "joltui";
import type MyApp from "../app.js";
@component({ tagName: "counter-button" })
export default class CounterButton extends CustomElement<MyApp> {
@react(0)
accessor count!: number;
override markup = () => html`
<p data-bind="count">Clicked {{= this.count }} times</p>
<button type="button" @click="increment">Click me</button>
`;
increment(): void {
this.count++;
}
}
To use it, import the module (importing is what registers the element) and write its tag in any template:
src/app/pages/homePage.ts
import "../components/counterButton.js";
// ...inside HomePage.markup
html`
<h1>Hello from JoltUI</h1>
<counter-button></counter-button>
`;
What happens:
@click="increment"connects the button'sclickevent to theincrementmethod.- Assigning
this.countinvalidates thecountbinding. - JoltUI re-evaluates the template of the element marked
data-bind="count", and only that element changes.
{{= ... }} is a doT expression evaluated with the component as
this. Reactivity explains bindings in detail.
Passing arguments¶
Attributes that start with : (short for data-jolt-) are the component's arguments:
override markup = () => html`
<p data-bind="count">{{! this.args.label }}: {{= this.count }}</p>
<button type="button" @click="increment">+1</button>
`;
Values are parsed as JSON when possible, so :start="10" arrives as the number 10.
Next steps¶
- Components: where markup comes from, events, arguments, selecting elements.
- Component communication: how components call each other.
- Routing: route parameters, navigation and titles.