Reusable HTML components powered by Alpine JS reactivity ๐ธ
<script
defer
src="https://unpkg.com/alpinejs-component@latest/dist/component.min.js"
></script>
<script defer src="https://unpkg.com/[email protected]/dist/cdn.min.js"></script>
npm install -D alpinejs-component
yarn add -D alpinejs-component
import Alpine from 'alpinejs'
import component from 'alpinejs-component'
Alpine.plugin(component)
Alpine.start()
You can render on page components by using a <template>
with an id
that
matches the template
attribute on the component.
Here we are rendering the component HTML found in <template id="person">
element.
<div
x-data="{
people: [
{ name: 'John', age: '25', skills: ['JavaScript', 'CSS'] },
{ name: 'Jane', age: '30', skills: ['Laravel', 'MySQL', 'jQuery'] }
]
}"
>
<ul>
<template x-for="person in people">
<x-component template="person" x-data="{ item: person }"></x-component>
</template>
</ul>
</div>
<template id="person">
<li>
<h2 x-text="item.name"></h2>
<p x-text="item.age"></p>
<ul>
<template x-for="skill in item.skills">
<li x-text="skill"></li>
</template>
</ul>
</li>
</template>
If you don't want on page components you can use the url
attribute which
accepts a path to the HTML component.
Here we are telling Alpine JS to fetch the HTML from /public/person.html
within the codebase.
<div
x-data="{
people: [
{ name: 'John', age: '25', skills: ['JavaScript', 'CSS'] },
{ name: 'Jane', age: '30', skills: ['Laravel', 'MySQL', 'jQuery'] }
]
}"
>
<ul>
<template x-for="person in people">
<x-component
url="/public/person.html"
x-data="{ item: person }"
></x-component>
</template>
</ul>
</div>
Then we'd have a file /public/person.html
which could look like this.
<li>
<h2 x-text="item.name"></h2>
<p x-text="item.age"></p>
<ul>
<template x-for="skill in item.skills">
<li x-text="skill"></li>
</template>
</ul>
</li>
You can pass template
or url
as a dynamic value, here's an example.
<div
x-data="{
components: [
{
template: '/public/person.html',
data: { name: 'John', age: '25', skills: ['JavaScript', 'CSS'] }
},
{
template: '/public/person.html',
data: { name: 'Jane', age: '30', skills: ['Laravel', 'MySQL', 'jQuery'] }
},
]
}"
>
<ul>
<template x-for="component in components">
<x-component
:template="component.template"
x-data="{ item: component.data }"
></x-component>
// Or
<x-component
:url="component.template"
x-data="{ item: component.data }"
></x-component>
</template>
</ul>
</div>
You can use styles
attribute to specify which stylesheets to include.
<style title="person">
/* ... */
</style>
<x-component
template="person"
styles="person"
x-data="{ item: person }"
></x-component>
You can also include multiple stylesheets by separating them with a comma.
<style title="person">
/* ... */
</style>
<style title="general">
/* ... */
</style>
<x-component
template="person"
styles="person,general"
x-data="{ item: person }"
></x-component>
Or, if you want to include all stylesheets you can use styles="global"
You can add a <style>
element with the components CSS to the component itself.
<div>
<style>
.example {
background: #00f;
}
</style>
<p class="example" x-text="message"> </p>
</div>
If you need to change the name x-component
, you can do so by setting the
global xComponent
object. This is necessary because blade components start
with x-
, which can cause conflicts.
window.xComponent = {
name: 'a-component',
}
You will then call components like this:
<div
x-data="{
people: [
{ name: 'John', age: '25', skills: ['JavaScript', 'CSS'] },
{ name: 'Jane', age: '30', skills: ['Laravel', 'MySQL', 'jQuery'] }
]
}"
>
<ul>
<template x-for="person in people">
<a-component
url="/public/person.html"
x-data="{ item: person }"
></a-component>
</template>
</ul>
</div>