How to make your Web Pages look Prettier with Alpine.js
I had a revelation the other day.
In the beginning…
I had this idea that to make your UI pretty and reactive you needed to be using Vue, Svelte, or some other web framework. Otherwise the page just sat there until you clicked a button, then reloaded. Silly, I now know.
Then I discovered AlpineJS, and realised I was completely wrong.
That animation above is the result of the markup below. Literally, that’s it.
<html>
<head>
<title>Alpine demo page</title>
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.8.2/dist/alpine.min.js"></script>
</head>
<body>
<div x-data="{ show: false }">
<label for="name">Please enter your name: </label>
<input type="text" name="name" x-ref="name">
<button
@click="show = !show"
x-text="show ? 'Stop saying hello' : 'Say hello'"
></button>
<div x-show="show">
<p x-text="'Hello ' + $refs.name.value"></p>
</div>
</div>
</body>
</html>
The magic happens with the x-
tags:
x-data
declares a variable - you can only use the variable within the scope of that blockx-show
decides visibilityx-text
controls theinnerText
of the element it’s on.@click
can be used as a shorthand for listening to events. It’s a shortcut forx-on
.x-ref
adds a reference to the element, making it accessible later through$refs
.
Put those together and you can do some amazing things.
Using it
On most of my projects I’ve had a separate page for deleting items. The flow wasn’t as smooth as I’d have liked, but it worked.
Then I had a Gru moment.
Why a whole separate page? All I actually need is a POST request to the right URL. I can do that with a form. We already know Alpine can show and hide the form.
Since there’s no data that has to be conveyed the form only actually has to surround the submit buttons.
<form action="/people/<%= person.id %>/delete" method="POST">
<div>
<button>Cancel</button>
<button type="submit" >Delete</button>
</div>
</form>
If we’re going to use Alpine then we need to tweak the form ever so slightly, replacing the cancel button.
<button @click.prevent="showDelete = false">Cancel</button>
The .prevent
stops the click event from being propagated up - if that wasn’t there then the button would register the click, and as well as hiding the delete dialogue it would actually submit the form and delete the item.
Let’s go along to the (really useful) Alpine toolbox, and we see that in fact there are already multiple modal examples that we can derive from.
This excellent post makes a good starting point. We replace the body of it with the tweaked form above and we get the following effect:
I took the chance to improve the look of the buttons slightly, since we’ve pulled in Tailwind from the example. Much better than having to click through to a separate page!