@mschop/alpine-web-components
v2.0.1
Published
Use alpinejs with web components and shadow root
Readme
alpine-web-components
This library helps you with using AlpineJS with web components. This includes web components using shadow root.
Install
- Make sure you have AlpineJS installed and ready.
- Install this library by running
npm i @mschop/alpine-web-components - Use classes AlpineWebComponent or AlpineComponent as base classes.
How to use it
The following example shows you a basic "Counter" example.
import AlpineWebComponent from "alpine-shadow-component";
import type {State} from "../../AlpineWebComponent";
interface CounterState extends State {
counter: number,
}
class Counter extends AlpineWebComponent {
state: CounterState = {
attributes: {},
counter: 1,
}
template = `
<span x-text=""></span>
<button @click="counter++">+1</button>
<button @click="component.resetCounter()">Reset</button>
`
resetCounter() {
this.state.counter = 1
}
useShadow(): boolean {
return false;
}
}
window.customElements.define('my-counter', Counter);You should now be able to reference the counter with <my-counter></my-counter>.
Note: Components are not automatically initialized. You need to call .init() on them. The common approach is to use x-init in the template:
<my-counter x-init="$el.init()"></my-counter>The component instance is attached as state.component but marked raw, so Alpine won't proxy the full custom element. You can call component methods from the Alpine scope:
<button @click="component.resetCounter()">Reset</button>Please see directory example for example on how to bind / update attributes etc..
Attribute-based state (string-only, isolated)
The default behavior mirrors component state to HTML attributes (and reads attributes back into state). This keeps the component interface purely declarative and works well for primitives (string/number/boolean).
Key points:
- Attributes are always strings, so complex data must be serialized (e.g. JSON) via
attributeCasts. - When state changes, the attribute is updated and an
updated-<key>event is emitted. - When an attribute changes externally, the component state is updated.
This approach is useful when you want a clean HTML-only API and strict isolation between components. For complex data, consider property binding with x-init (see section above).
Passing complex data (avoid JSON in attributes)
Attributes are strings, so passing objects requires JSON encoding/decoding. If you want to share complex data (objects, arrays, reactive proxies) between components, bind a property instead of an attribute.
Alpine's x-init run once on init. So you can simply passing complex objects by passing the value in x-init.
<my-child x-init="
$el.state.shared = parentState;
$el.init();
"></my-child>This keeps the template declarative while passing the actual object reference. Use attributes for primitives and properties for complex data.
