starting with alpine

2021-08-25

alpine javascript

What Is Alpine?

Alpinejs is an extremely lightweight javascript framework that makes it super simple to add functionality to your sites.

Why Alpine?


Alpine is super lightweight, so you can add it with a single script instead of needing an entire build process. Alpine is NOT an SPA framework. It's more of a modern alternative to jQuery than a competitor to react. I find its perfect place to be on sites where you don't want a whole SPA (as most sites do not need one), so it fits nicely with a webserver based app, like one built with Django or Phoenix. Its small size also makes it great for statically rendered sites like this one.

Getting Started


Adding alpine to your site is as simple as adding one script tag.

<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>

This will give you the latest version of alpine 3.

You can swap the 3 with a 2 if you need ie compatability.

For a first example we'll build a simple clicker.

x-data


The primary way of using alpine is through attribute tags. The one that turns an html element into an alpine component and makes alpine listen to it is x-data. You give it a javascript object that will hold your state.

<div x-data="{count: 0}">
...
</div>

With that, anything inside the div will be monitored by alpine, and be able to access the data.

x-text


Another attribute tag. This one will set the innerText of the element it is on to be whatever field you'd like.

<span x-text="count"></span>

With that the span will always update to have the count property from the x-data as its value.

x-on


x-on is our event listener, which allows us to react to javascript events from alpine.

<button x-on:click="count++">click</button>

You can also use the short hand @, for example

<button @click="count++">click</button>

With either of those on an element alpine will lisen for click events, and increment our counter.

Bringing It All Together.


So combining our x-data, x-on and x-text we can get a functional clicker.

<div x-data="{count: 0}">
<button @click="count++">click</button>
<span>count: </span><span x-text="count">
</div>

You can try this code below:

count:

A Bigger Example


As a slightly larger example, to showcase one more important bit of functionality we will build a todo list.

Component Functions

You don't have to declare your attributes in the data attribute directly. You can reference a function that manages it for you.

We will start our app with a todo array, and a newTodo string.

<div x-data="todoApp()">
...
</div>

...

<script>
function todoApp() {
return {
newTodo: '',
todos: [],
}
}
</script>

x-model


Alpine employs 2-way data binding, and its method of doing so is through x-model. To add to our existing example

<div x-data="todoApp()">
<input placeholder="todo..." x-model="newTodo" />
</div>

x-for


x-for is alpines utility for iterating over a list of items.

There are two things to note with x-for:

  • x-for must be on a template element.
  • x-for must have a single child element.

you can also add a :key attribute to help with ordering on item removal/addition.

<div x-data="todoApp()">
<input placeholder="todo..." x-model="newTodo" />
<ul>
<template x-for="todo in todos">
<li x-text="todo"></li>
</template>
</ul>
</div>

Component functionality


You can also add functionality to the component function that you are using. One thing to note is that whenever you use data in the component you must reference it with this like so.

...

<script>
function todoApp() {
return {
newTodo: '',
todos: [],
addTodo() {
this.todos.push(this.newTodo)
this.newTodo = ''
}
}
}
</script>

Sub-methods

Several Alpine attributes have sub-methods to allow additional functionality. A helpful one is @click.prevent which adds event.preventDefault() to your click handler automatically so that, for instance, a form won't refresh your page for instance.

<div x-data="todoApp()">
<input placeholder="todo..." x-model="newTodo" />
<button @click.prevent="addTodo">click</button>
<ul>
<template x-for="todo in todos">
<li x-text="todo"></li>
</template>
</ul>
</div>

Final code

And with that we have our final code for the project

<div x-data="todoApp()">
<input placeholder="todo..." x-model="newTodo" />
<button @click.prevent="addTodo">click</button>
<ul>
<template x-for="todo in todos">
<li x-text="todo"></li>
</template>
</ul>
</div>
...

<script>
function todoApp() {
return {
newTodo: '',
todos: [],
addTodo() {
this.todos.push(this.newTodo)
this.newTodo = ''
}
}
}
</script>

You can try it out below.

AboutMe

Husband. Father. Programmer.

Check me out on github

Want some help or work done? get in touch

TechStack

11ty - Static site generator

tailwindcss - Utitlity first css

Alpine.js - lightweight javascript interactions