What is Alpine.js?
Free Preview
Learn what Alpine.js is and how to build reactive JavaScript interfaces using simple HTML attributes.
Lesson Content
Alpine.js is a JavaScript library which provides the ability to create reactive interfaces in a very simple syntax by using HTML attributes. You can think of it kinda like jQuery, but for reactivity.
Just HTML attributes
We can use an x-data HTML attribute to store a piece of state, which is essentially a variable that can be changed and tracked over time. Then, we can change the value of that state with an x-on:click attribute:
<div x-data="{ show: false }">
<button x-on:click="show = true">Show Content</button>
<button x-on:click="show = false">Hide Content</button>
<div x-show="show">Content to show or hide</div>
</div>
Clicking either button changes the value of the show property. But more importantly, any time that value changes, the related HTML will also be re-rendered in front of your eyes, without the page needing to be reloaded.
What's really neat about this is that, besides the x-data object and the simple variable assignments, we didn't really write any JavaScript. We created a fully interactive UI with plain HTML.
Shorthand syntax
Custom HTML attributes such as x-on:click (which are called "directives") can be a bit verbose, but Alpine also provides a shorthand syntax that does the same thing.
For example, x-on:click can be replaced with @click:
<div x-data="{ show: false }">
<button @click="show = true">Show Content</button>
<button @click="show = false">Hide Content</button>
<div x-show="show">Content to show or hide</div>
</div>
When binding pieces of state to certain attributes, we can also use other shorthand directives. For example, if we wanted to hide the button that wouldn't do anything given the current state, we can use the :class format (shorthand for x-bind:class):
<style>
.hidden { display: none; }
</style>
<div x-data="{ show: false }">
<button @click="show = true" :class="!show || 'hidden'">Show Content</button>
<button @click="show = false" :class="show || 'hidden'">Hide Content</button>
<div x-show="show">Content to show or hide</div>
</div>
The :class expression here is a JavaScript shortcut -- !show || 'hidden' means "if show is already true, add the hidden class to this button, since clicking it again wouldn't change anything." This is a very succinct and terse way to write and keep logic simple.
Additional functionality with JavaScript
The examples above are really simple, and are a great way to get started with Alpine. That said, you can also store state, create reactive functions, define custom directives and more in your own JavaScript, which extends the core functionality.
// Responding to events with effect()
let button = document.querySelector('button')
let span = document.querySelector('span')
let data = Alpine.reactive({ count: 1 })
Alpine.effect(() => {
span.textContent = data.count
})
button.addEventListener('click', () => {
data.count = data.count + 1
})
// Creating a custom directive
Alpine.directive('uppercase', el => {
el.textContent = el.textContent.toUpperCase()
})
<!-- Calling custom functions -->
<span x-text="getLabel"></span>
<script>
async function getLabel() {
let response = await fetch('/api/label')
return await response.text()
}
</script>
Beyond the basics
This is just the tip of the iceberg for Alpine.js. The full documentation covers everything that's available at alpinejs.dev.
<div x-data="{ show: false }">
<button x-on:click="show = true">Show Content</button>
<button x-on:click="show = false">Hide Content</button>
<div x-show="show">Content to show or hide</div>
</div><div x-data="{ show: false }">
<button @click="show = true">Show Content</button>
<button @click="show = false">Hide Content</button>
<div x-show="show">Content to show or hide</div>
</div><style>
.hidden { display: none; }
</style>
<div x-data="{ show: false }">
<button @click="show = true" :class="!show || 'hidden'">Show Content</button>
<button @click="show = false" :class="show || 'hidden'">Hide Content</button>
<div x-show="show">Content to show or hide</div>
</div>// Responding to events with effect()
let button = document.querySelector('button')
let span = document.querySelector('span')
let data = Alpine.reactive({ count: 1 })
Alpine.effect(() => {
span.textContent = data.count
})
button.addEventListener('click', () => {
data.count = data.count + 1
})// Creating a custom directive
Alpine.directive('uppercase', el => {
el.textContent = el.textContent.toUpperCase()
})<!-- Calling custom functions -->
<span x-text="getLabel"></span>
<script>
async function getLabel() {
let response = await fetch('/api/label')
return await response.text()
}
</script>
Join the discussion!
Comments
Want to comment on this lesson?
Enroll in this course to leave comments.