Adds the ability to define widgets using Alpinejs
It's implemented using WebComponents but it favors keeping the component state in the scope of the component rather than embedding it as attributes on the dom nodes.
<!-- Step 1. Define the Widget -->
<template x-data x-widget="x-button">
<button x-data="xWidget({label: ''})($el, $data)" x-text="label"></button>
</template>
<!-- Step 2. Use the widget -->
<div x-data="{message: 'Click me'}">
<x-button :label="message" @click="message='Thanks'"></x-button>
</div>
- Install x-widget npm package:
npm install x-widget
- Install xWidget plugin for Alpine.js:
import xWidget from 'x-widget'
Alpine.plugin(xWidget)
<template x-data x-widget="x-panel">
<div>
<template x-if="$slots.header">
<div class="header">
<slot name="header"></slot>
</div>
</template>
<div>
<slot></slot>
</div>
</div>
</template>
<x-panel>
<!-- Named Slot -->
<template slot="header">
<h1>Panel Header</h1>
</template>
<!-- Default Slot -->
<template>
<p>Panel Content</p>
</template>
</x-panel>
Widget data is a helper that lets you to define the properties, data types, and the defaults your widget expects.
It supports giving values for properties using attributes, as well as a new x-prop
mechanism that makes it easy to have two-way binding of scope data and widget properties.
In the example below, clicking on "Close" will set showDropdown
to false.
<template x-data x-widget="x-dropdown">
<div x-data="xWidget({ open: false, items: [] })($el, $data)">
<div x-show="open">
<button @click="open = false">Close</button>
<template x-for="item of items">
<option :value="item.value" x-text="item.label"></option>
</template>
</div>
</div>
</template>
<div x-data="{showDropdown: true}">
<x-dropdown
x-prop:open="showDropdown"
x-prop:items="[{value: 1, label: 'One'}, {value: 2, label: 'Two'}]"
></x-dropdown>
</div>
If you don't like the look of having the widget's spec in the DOM, you can use the following approach too:
<script>
import { xWidgetData } from 'x-widget'
Alpine.data(
'xDropdown',
xWidgetData({
open: false, // define show as a boolean with default value of false
items: [] // define items as an array with default value of []
})
)
</script>
<template x-data x-widget="x-dropdown">
<div x-data="xDropdown($el, $data)">
<div x-show="open">
<button @click="open = false"></button>
<template x-for="item of items">
<option :value="item.value" x-text="item.label"></option>
</template>
</div>
</div>
</template>