A component is a factory that returns a fresh state object. Each element using it gets its own instance, so three ratings on a page never interfere. Arguments in kj-data="rating(4, 'Docs')" are passed to the factory, and an init(el) method receives the root element if you need it.
Register components in a script that runs before the DOM is ready — placing it right after the jsKjs script tag is enough.
View the source for this demo
<div kj-data="rating(4, 'Docs')" class="rate"></div>
<div kj-data="rating(2, 'Demos')" class="rate"></div>
<div kj-data="rating(0, 'Release notes')" class="rate"></div>$.component('rating', (initial = 0, label = 'Rating') => ({
value: initial, label,
init(el) { // build the widget's markup once
el.innerHTML =
'<span class="rate-label" kj-text="label"></span>' +
'<div class="stars" role="group" aria-label="' + label + ' rating">' +
[1, 2, 3, 4, 5].map(n => '<button type="button" @click="rate(' + n + ')" :aria-pressed="value >= ' + n +
' ? \'true\' : \'false\'" aria-label="' + n + ' star' + (n > 1 ? 's' : '') + '">★</button>').join('') +
'</div><span class="muted" kj-text="value ? value + \' of 5\' : \'Not rated\'" aria-live="polite"></span>';
},
rate(n) { this.value = this.value === n ? 0 : n; }, // click the same star again to clear
}));More examples
A dropdown component
$.component('dropdown', (open = false) => ({
open,
toggle() { this.open = !this.open; },
}));
// <div kj-data="dropdown(true)"> <button @click="toggle()">Menu</button> <ul kj-show="open">…</ul> </div>API
Register a reusable component factory, then use it with kj-data="name" or with arguments: kj-data="name(4, 'Docs')". An init(el) method receives the root element.
Declares a component and its reactive scope. An init() method, if present, runs on mount. Pass a registered component name to reuse logic.
Migrating
Alpine.data('rating', …) → $.component('rating', …), including arguments: x-data="rating(4)" → kj-data="rating(4)".Related features
Reactive state
Declare state on an element with kj-data and every binding inside updates when it changes.
Open →PulseGlobal stores
Share state between components with $.store(name, data).
Open →PulseAttribute binding
Bind any attribute to state with :attr or kj-bind:attr — src, alt, aria-*, disabled, style.
Open →