AlpineJS Hidden Gems

Published September 29th, 2020
5 minute read

It's no secret — I'm a huge fan of Alpine. For me, it hits that goldilocks zone between minimalistic and powerful. Alpine is straightforward to get started with, especially if you have a VueJS background. However, there are a few hidden features (okay, they're documented, not actually hidden) that you may not notice if you're just quickly scanning the readme.

Easy Show / Hide Transitions

Alpine includes support for custom transition classes via x-transition, but did you know there's also an easier way to add show/hide transitions to your components? The x-show directive also has an optional modifier transition. Check it out:

<!-- no transition -->
<div x-show="open">I will appear abruptly with no transition.</div>

<!-- easy fade + scale -->
<div x-show.transition="open">I come and go with a nice transition.</div> 

Beats having six lines of x-transition class mappings for 80% of cases. However, it doesn't stop there! The transition modifier on x-show also has other optional modifiers.

<!-- Modify the transition -->
<div x-show.transition.in="open">Only transition in.</div>
<div x-show.transition.out="open">Only transition out.</div>
<div x-show.transition.opacity="open">Only fade (no scaling).</div>
<div x-show.transition.scale="open">Only scaling (no fade).</div>
<div x-show.transition.duration.2000ms="open">Transition in for two seconds. Out for half of that.</div>
<div x-show.transition.origin.top.left="open">Transition starts and ends from the top left</div>

<!-- Combine modifiers. Go crazy! -->
<div x-show.transition.in.origin.top.left.opacity="open">
	Only transition in from the top left with a fade. 
</div>

For more examples, check out the full documentation of x-show.

Camel Modifiers

Both x-bind and x-on support a .camel modifier. I find the latter one is more useful (especially when working with Livewire), but they're both good to know about.

x-bind

<div x-bind:attribute-name.camel="someVar">...</div>

<!-- Result -->
<div attributeName="(value of someVar)">...</div>

x-on

<div x-on:your-event.camel="doSomething">

<!-- Result -->
<div @yourEvent="doSomething">

Model Modifiers

There are two modifiers you can use with x-modeldebounce and number. Both can be useful in the right situations. I didn't know that number existed before writing this article!

Debounce

Delay updating the binding until a certain amount of time has passed since inputting something. In other words, when you stop typing it waits a little bit before updating the data. By default the time is 250ms, but you can customize the debounce time if you wish.

<input x-model.debounce="name"> <!-- 250ms default -->
<input x-model.debounce.500="name"> <!-- 500ms -->
<input x-model.debounce.500ms="name"> <!-- 500ms -->

Number

This modifier tries to cast the value to a number instead of the string representation of that number. If it can't cast it easily to a number, the original value is returned unmodified.

<input x-model.number="age">

The x-spread Operator

When you start to create more complex components, separating the logic and the template is a great pattern. If you come from a Vue background, you'll know this as single file components (.vue files). Separating template and logic is a great step, but the x-spread object lets you take it even further by encapsulating the attribute bindings too! Take this component example:

<div x-data="dropdown()">
    <button @click="show">Open</button>

    <div x-show="open" @click.away="hide">
        Dropdown contents
    </div>
</div>

<script>
    function dropdown() {
        return {
            open: false,
            show() { this.open = true },
            hide() { this.open = false },
        }
    }
</script>

Here's how it might look if we used x-spread.

<div x-data="dropdown()">
    <button x-spread="trigger">Open</button>

    <div x-spread="contents">
        Dropdown contents
    </div>
</div>

<script>
    function dropdown() {
        return {
            open: false,
			trigger: {
				['@click']() { this.open = true }
			}
			contents: {
				['x-show']() { return this.open },
                ['@click.away']() {
                    this.open = false
                },
			}
        }
    }
</script>

I tried to keep the example small for this article, but you can imagine how useful this might be when you have many attributes on a component. You no longer have to cross-reference the HTML and the Javascript sections of components to figure out what's happening. Instead, x-spread allows you to put everything in one spot.

Thanks for reading!

Enjoy this article? Follow me on Twitter for more tips, articles and links.
😢 Awww, nobody has liked or mentioned this on Twitter yet.

Join the Newsletter ❤️

A most excellent monthly newsletter with code & design tips, curated links and more!
Don't worry, I'll never send you spam. Unsubscribe at any time.