An Alternative Approach to Computed Properties in Alpine.js
This post was published 4 years ago. Some of the information might be outdated!
The other day, I wrote an article on how to achieve a similar effect to computed properties in Alpine.js. The approach that I took involved simply calling a method that returned a value:
<div x-data="data()">
<span x-text="hello()"></span>
</div>
<script>
function data() {
return {
hello: function () {
return "Hello!"
}
}
}
</script>
This works quite well, but they're not really properties anymore. The <span>
is still reactive, so if the return value depended on another data property, the UI would be updated when the dependency gets changed. To my eyes, property()
isn't as pretty as property
on its own.
Today though, I saw a tweet from Sebastian De Deyne that took a different approach to the same concept.
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>@calebporzio Quick Alpine question, can I use getters in x-data, or am I going to shoot myself in the foot somehow? pic.twitter.com/nBo4YcVNzZ
— Sebastian De Deyne (@sebdedeyne) April 21, 2020
This approach just didn't occur to me at first. It's probably because I hadn't actually tried it. The first thing I did was hop into CodePen and try it out:
See the Pen Getters Alpine.js by Ryan Chandler (@ryangjchandler) on CodePen.
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>Out of the box, it just works! Click the button on the right and watch the <span>
below update. I almost feel kind of stupid that I hadn't though of this originally. Since Alpine is using an object literal as its source of data, we can use all of the normal things an object provides, such as getters and setters.
The other added benefit this method provides is that you don't need to add the parentheses anymore because when Alpine tries to access the property, the JavaScript engine will recognise that there is a getter defined and call that for us.
Browser compatibility
Regular getters
and setters
are supported in all modern browsers and ... 🥁 all the way back to Internet Explorer 9. The only thing that isn't supported that far back is computed property names, so you can't do things like:
function data() {
return {
get [expression]() {
return 'Hello!'
}
}
}
The expression is dynamic and acts like a fallthrough if the property doesn't exist or doesn't have a getter defined already. That's not a big deal, because nobody should be using IE9 today. Seriously, nobody.
Sign off
Thanks to Sebastian for tweeting about this. You can read some of his blog posts on his personal blog too.
Personally I'm going to be using this approach going forward, especially since the browser support is so good (unusual, I know).