Alpine.js 101: Understanding the basics in 3 minutes!
Let’s talk about a very minimalist javascript library.
We are going to discuss alpine, which can potentially replace libraries like jQuery or even Angular, React, or Vue which you usually use while developing a website.
If you regularly build sites that require some sprinkling of JavaScript on your UI, to give a better user experience, this article is for you!!
After doing a lot of research and even using it numerous times, I realized that Alpine.js might really be onto something.
Alpine.js vs others
If you have a look at this table, you will actually see the difference in filesize between alpine and other commonly used libraries/frameworks.
Like many other developers, we usually overcomplicate our workflow.
We always choose for the latest and most popular libraries. We go to the best libraries we can find online. We see that React, Angular, and Vue have the highest search ranks, and blindly start using them.
I think that's a wrong approach because in many cases those libraries are overkill and nothing else.
I'm not trying to take anything away from frameworks like Angular and React. I actually use them on a day-to-day basis and I actually have all my codebases in angular multiple projects. What I'm trying to say is that there are some websites that don't need those complex and advanced frameworks, because they really add to the size, and you can actually see this in the table above.
When (and when not) to use Alpine
If you're thinking to use Alpine in your next project, let me clear a few things up for you.
When to avoid Alpine =>
You should NOT reach out for libraries like alpine when your website:
Have a lot of data manipulations
Requires enormous validations.
Have to go through numerous API calls to fetch and process data.
For these scenarios, I would really really recommend you to use Vue, React, Angular, or any other framework that you're a fan of.
When to use Alpine =>
You should only reach out for libraries like alpine when your website:
Have to do basic manipulation on the DOM.
Under some conditions, you have to append classes on user interaction
Listen to some events and alter the UI.
I think in these scenarios Alpine.js is your best friend.
Installation
CDN:
To start, you simply need to add this script tag to the <head>
:
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js" defer></script>
That's it. It will initialize itself!
NPM:
If you prefer installing the package from npm
:
npm i alpinejs
Creating a basic dropdown
Let's get started with an actual example.
If we click on this button, the drop-down is visible/open. If we click again, it goes away.
Let’s understand the code now =>
<div x-data="{ open: false }">
<button @click="open = true">Open Dropdown</button>
<ul
x-show="open"
@click.away="open = false"
>
Dropdown Body
</ul>
</div>
As you can see in the code, there are some things that come from Alpine, which are not native HTML. For example, x-data, @click, x-show, etc.
x-data is basically the data we pass into the component (or div in this case). It has an object that can have some attributes and can even have functions. In this case its
{open: false}
.With the click, using the @click property of this button, the variable open should be equal to true. What happens then? In the background, we have an unordered list which is basically the drop-down body and it becomes visible depending on the value of the open variable. So if the open is true, we will actually see the ul or the list and whenever we click away from the drop-down body, the variable open is assigned a value to be false, which then hides the dropdown.
With the help of @click.away, if we click anywhere else on the screen, open = false is triggered, hiding the dropdown again!
So that was pretty simple and you can already see the power of this library.
Building a Twitter-style character counter
Let's go through a little more complicated example: let's build a character counter with alpine.
In which we basically have a text area and below that, we have the number of characters that can be entered. We'll allow the users to enter 180 characters and we'll update the count on every input below the text area.
Recommended: Install Alpine IntelliSense for VsCode so that it gives you relevant autocompletes.
Step 1: Let’s start with the basic skeleton
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js" defer></script>
</head>
<body>
<div class="header">
<h2>Character counter with Alpine</h2>
</div>
</body>
</html>
Step 2: Sprinkle some Alpine
<body>
<div class="header">
<h2>Character counter with Alpine</h2>
</div>
<div x-data="{
content: '',
limit: 180
}">
<textarea></textarea>
<p></p>
</div>
</body>
Let’s pass an object in x-data for the div. Let's say we have some content (a string
), which is empty right now and we have a limit equal to 180.
Also, there is a textarea
and below that, we have a paragraph that will finally display the character count.
Note: I have actually added some styling beforehand, but you don't need to worry about it.
Complete code is at the end of this tutorial!
Step 3: Logic
The remaining()
function below should basically return the difference between the content’s length and the limit.
<div x-data="{
content: '',
limit: 180,
remaining() {
return this.limit - this.content.length
}
}">
<textarea x-model="content"></textarea>
<p>
You have <span x-html="remaining()"></span> character left!
</p>
</div>
A span, because we actually want to calculate the difference between the limit and the content.
The easiest way is to create a
remaining()
function, which will basically return the difference between the limit and the length of the content.Let’s use
x-html
and call this inside the span. This would update the inner HTML content of the span with the return of theremaining()
function.At the moment, Alpine doesn't know what we have inside the
textarea
as it doesn't know what the content is. How can I bind this content variable with my text area? We can use thex-model
for that.
VOILA!
We have a pretty good working application, which basically tells us how many characters you have entered or how many characters you can enter at the moment.
Complete Code
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js" defer></script>
<style>
textarea {
width: 95%;
height: 150px;
padding: 12px 20px;
box-sizing: border-box;
border: 2px solid #ccc;
border-radius: 4px;
background-color: #f8f8f8;
resize: none;
margin-top: 20px;
margin-left: 2.5%;
}
p {
margin-left: 2.5%;
}
.header {
padding-top: 10px;
padding-bottom: 10px;
text-align: center;
background: #1abc9c;
color: white;
width: 95%;
margin-left: 2.5%;
}
</style>
</head>
<body>
<div class="header">
<h2>Character counter with Alpine</h2>
</div>
<div x-data="{
content: '',
limit: 180,
remaining() {
return this.limit - this.content.length
}
}">
<textarea x-model="content"></textarea>
<p>
You have <span x-html="remaining()"></span> character left!
</p>
</div>
</body>
</html>
I hope this article helped you to understand the basics of Alpine.js
Thanks for reading. If you have any questions, feel free to leave a response.
Resources
https://github.com/alpinejs/alpine
https://www.smashingmagazine.com/2020/03/introduction-alpinejs-javascript-framework/
https://www.alpinetoolbox.com/
Why?