Installing and Using Alpine
While you can install Alpine via npm (npm install alpinejs), the simplest way is to drop in a script tag in the head of your HTML page:
<script defer src="https://unpkg.com/[email protected]/dist/cdn.min.js"></script>
The 3.x.x used in the URL above locks the library to the current major version which is definitely recommended. (I speak from personal experience when a number of CodePens I had using a CDN for Vue broke when they switched from loading 2.x to 3.x. That was definitely my fault however!)
The next step involves figures out where you want Alpine to work. Much like when you use Vue to progressive enhance a page, Alpine requires you to “mark” the area it will be involved in. So for example, perhaps you have a form that you want to enhance with custom validation or perhaps you’re building an Ajax-driven search field. Once you figure out where in your page you’ll be doing “dynamic stuff”, you let Alpine know by adding the x-data attribute. So for example:
<!-- Let's do cool stuff here! -->
<div x-data="">
<!-- more stuff here... -->
</div>
Alpine.js Template Directives
Now let’s actually do stuff. The x-data attribute used earlier can define variables we use within our Alpine application. So for example, let’s define a name and age:
<!-- Let's do cool stuff here! -->
<div x-data="{
name:'Raymond Camden',
age:49
}">
<!-- more stuff here... -->
</div>
We’ve defined data, but how do we use it? There’s multiple template options that can be used here. First, x-text will simply render the value out. Here’s an example:
<div x-data="{
name:'Raymond Camden',
age:49
}">
<p>
My name is <span x-text="name"></span> and I'm
<span x-text="age"></span> years old.
</p>
</div>
Along with x-text, you can use x-html. Separating the two directives makes it a bit safer as it reduces the chance of accidentally including invalid or insecure HTML into the DOM. Let’s add a bio value and render it.
<div x-data="{
name:'Raymond Camden',
age:49,
bio:'I am truly <strong>cool</strong>.'
}">
<p>
My name is <span x-text="name"></span> and I'm
<span x-text="age"></span> years old.
</p>
<p x-html="bio"></p>
</div>
The result:
There’s other directives for displaying data of course. Conditions can be done with either x-if or x-show. The x-if directive completely adds or removes content from the DOM whereas x-show will use CSS to hide something. In both cases, it takes an expression that should evaluate to true. Let’s add a new value for coolness and check for it in our document.
Both directives should be used in an <template> directive, not the actual item you want to show or hide. Also note there is not a x-else directive, but you can use another directive with the opposite logic to get the same result. Here’s an example:
<div x-data="{
name:'Raymond Camden',
age:49,
bio:'I am truly <strong>cool</strong>.',
cool:false
}">
<p>
My name is <span x-text="name"></span> and I'm
<span x-text="age"></span> years old.
</p>
<p x-html="bio"></p>
<template x-if="cool">
<p>
Yes, you are cool!
</p>
</template>
<template x-if="!cool">
<p>
Sorry, you aren't as cool as you think you are.
</p>
</template>
</div>
You’ll notice I first check if cool is true and then check if it is not true (!cool). You can test this yourself and simply modify that cool value to see the results.
Lastly, you can loop over arrays of data using the x-for directive. Here’s an example where we’ve added an array of cats and then render it in a bulleted list. Like the previous example, we must use the <template> tag again.
<div x-data="{
name:'Raymond Camden',
age:49,
bio:'I am truly <strong>cool</strong>.',
cool:false,
cats: ['Luna', 'Pig', 'Elise' ]
}">
<p>
My name is <span x-text="name"></span> and I'm
<span x-text="age"></span> years old.
</p>
<p x-html="bio"></p>
<template x-if="cool">
<p>
Yes, you are cool!
</p>
</template>
<template x-if="!cool">
<p>
Sorry, you aren't as cool as you think you are.
</p>
</template>
<h2>My Cats</h2>
<ul>
<template x-for="cat in cats">
<li x-text="cat"></li>
</template>
</ul>
</div>
Now we’re getting somewhere…
Data and Two Way Binding
Up until this point, we’ve simply rendered the data given to us. But Alpine also supports two way binding. This can be used to connect form fields with data in either direction. To bind a form element, you use x-model. Let’s add fields for our name and coolness factor:
<div x-data="{
name:'Raymond Camden',
age:49,
bio:'I am truly <strong>cool</strong>.',
cool:false,
cats: ['Luna', 'Pig', 'Elise' ]
}">
<p>
My name is <span x-text="name"></span> and I'm
<span x-text="age"></span> years old.
</p>
<p x-html="bio"></p>
<template x-if="cool">
<p>
Yes, you are cool!
</p>
</template>
<template x-if="!cool">
<p>
Sorry, you aren't as cool as you think you are.
</p>
</template>
<h2>My Cats</h2>
<ul>
<template x-for="cat in cats">
<li x-text="cat"></li>
</template>
</ul>
<p>
New Name: <input x-model="name">
</p>
<p>
Am I cool?
<select x-model="cool">
<option value="true">Yes</option>
<option value="false">No</option>
</select>
</p>
</div>
Now you can edit either form field and see the HTML above change in real time.
While the previous demo shows an input and select field, note that you can use it with any form field, including checkboxes and radio buttons.
Handling Events the Alpine.js Way
Alpine provides event handling support via x-on but like Vue, provides a shortcut with the @ directive. You supply the name of the event you care to handle and the code to run when the event fires:
button x-on:click="handleButton">Click Me</button>
Or:
<button @click="handleButton">Click Me</button>
Now when clicked, Alpine will run the function handleButton, but where is that defined? Why back in our x-data of course. Here’s our updated parent div:
<div x-data="{
name:'Raymond Camden',
age:49,
bio:'I am truly <strong>cool</strong>.',
cool:false,
cats: ['Luna', 'Pig', 'Elise' ],
handleButton() {
alert('Button clicked');
}
}">
Alpine supports multiple modifies for event handling. So for example, a typical use case is to prevent a form from submitting when clicking the submit button. This can be done by adding .prevent, for example:
<input type="submit" @click.prevent="handleFormat">
Check the modifiers docs for a full list of these ways of handling events.
Binding HTML Attributes via Data
Earlier you saw how x-model let you bind form fields to data, but what about other attributes? By using x-bind, you can bind arbitrary HTML attributes to your data. As with events, there’s also a shorthand, :.
So for example, let’s add an image URL:
<div x-data="{
name:'Raymond Camden',
age:49,
bio:'I am truly <strong>cool</strong>.',
cool:false,
cats: ['Luna', 'Pig', 'Elise' ],
handleButton() {
alert('Button clicked');
},
catImage: 'https://placekitten.com/500/500'
}">
We can then use it via:
<img x-bind:src="catImage">
Or:
<img :src="catImage">