Pulse · Alpine-style

Reusable components

Register once, use anywhere: $.component('rating', (initial, label) => ({ … })), then <div kj-data="rating(4, 'Docs')">.

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.

Live · Three independent ratings, one component

View the source for this demo
HTML
<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>
JavaScript
$.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

JavaScript
$.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

$.component(name, (...args) => state)

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.

Reference: $.component() →
kj-data="{ … }" | kj-data="componentName"

Declares a component and its reactive scope. An init() method, if present, runs on mount. Pass a registered component name to reuse logic.

Reference: kj-data →

Migrating

Coming from Alpine.jsAlpine.data('rating', …) → $.component('rating', …), including arguments: x-data="rating(4)" → kj-data="rating(4)".

Related features