Notice: This article will work with Alpine v2, if you are using V3 you can checkout this new article on Setting Alpine Data Outside of the Component or you may choose to use the new Alpine Store functionality 😉
I've been becoming a huge fan of AlpineJS lately. Mostly because of how seamless it works with Livewire, but also because it's lightweight and easy to work with.
While working on a project using Alpine I needed a way to change a variable from outside of the element itself, and that's what we'll learn in this quick tutorial.
A Quick Example
As an example I'll create a simple button and a box. When I click the button it will toggle the box display on and off. This can be easily accomplished using Alpine like so:
<div x-data="{ showBox: true }">
<button @click="showBox = !showBox">Toggle</button>
<div x-show="showBox" style="width:50px; height:50px; background:red"></div>
</div>
This will result in the following example:
Pretty simple stuff, right? But, what if we wanted to click a button outside of the element itself? Something like this:
<div id="container" x-data="">
<button @click="showBox = false">Hide Box</button>
<div x-data="{ showBox: true }">
<button @click="showBox = !showBox">Toggle</button>
<div x-show="showBox" style="width:50px; height:50px; background:red"></div>
</div>
</div>
Well, that's not going to work because we are calling showBox = false
outside of the place it was created. So, the Hide Box button is pretty much, useless.
The Solution
This is where we'll learn the magic of __x
🤙
Changing the data from outside of our element means that we need a way to talk to the element and get the variable. We can do that by giving our element an ID, like so:
<div id="redBox" x-data="{ showBox: true }">
<button @click="showBox = !showBox">Toggle</button>
<div x-show="showBox" style="width:50px; height:50px; background:red"></div>
</div>
Now, if we wanted to get that showBox
variable we can retrieve it from the window namespace using javascript like so:
window.hideBox = function(){
document.getElementById('redBox').__x.$data.showBox = false;
}
Our full solution would look like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Access Alpine Variables</title>
</head>
<body>
<div x-data="{ data: true }">
<button @click="hideBox()">Hide Box</button>
<div id="redBox" x-data="{ showBox: true }">
<button @click="showBox = !showBox">Toggle</button>
<div x-show="showBox" style="width:50px; height:50px; background:red"></div>
</div>
</div>
<script>
window.hideBox = function(){
document.getElementById('redBox').__x.$data.showBox = false;
}
</script>
<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js"></script>
</body>
</html>
Not too shabby 😉
Conclusion
AlpineJS is still a fairly new javascript library, but there is huge potential. There may be a better way to do this in the future or there may be a better way right now 😂, but this worked for me, so I thought I would share my solution.
If you are new to Alpine, you may want to check out my Intro to AlpineJS tutorial. Additionally, be sure to checkout Alpine repo at https://github.com/alpinejs/alpine and give it a star ⭐