Skip to content

allain/x-widget

Repository files navigation

x-widget

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.

Usage

<!-- 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>

Installing x-widget

  1. Install x-widget npm package:
npm install x-widget
  1. Install xWidget plugin for Alpine.js:
import xWidget from 'x-widget'
Alpine.plugin(xWidget)

Using Slots

<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

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>

About

WebComponents for Alpine.js

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published