Syncing Livewire and Alpine0:58
Yeah, then you could say, well, if you click on this, then set $show to false. But again, this is where it often gets tricky. Because on one side, we're using Livewire to control state on the server, as you see here. But then it also sounds like we need to control that state for convenience on the front end. So often, you'll end up in this situation where you're using both Livewire and Alpine, and you want a particular property to be in sync. So for example, if this changes to true, I magically want the Alpine value for $show to also be set to true.
Using the entangle directive1:26
So for example, if this changes to true, I magically want the Alpine value for show to also be set to true. And then if I were to change it on the Alpine end, I would then want it to update on the Livewire end. We want them to be in sync. So luckily, Livewire 2 makes this really easy. If we go to the website, it is a directive called entangle. Let's have a look here. There we go. Sharing state between Livewire and Alpine.
There we go. Sharing state between Livewire and Alpine. So by using entanglement, we are now able to control the state of the dropdown from both Alpine and Livewire. When one value changes, the other will also be changed. This is exactly what we want. Okay, so let's have a look. We can say entangle, and what is the property? Well, if we come back, it's called showModal. So just this once, I'm gonna put it in here, but
Well, if we come back, it's called showModal. So just this once, I'm gonna put it in here, but then we're gonna talk about why, not a good idea. But it should at least get us going. So this right here looks a little confusing with the @ symbol. Think of it just like a Blade directive, because it is a Blade directive. It's just going to expand to hunt down the corresponding Livewire component. I'll show you. If we give this a refresh, open this up. In Chrome DevTools, if I have a look here, yeah, so
If we give this a refresh, open this up. In Chrome DevTools, if I have a look here, yeah, so notice there's no reference to @entangle. That directive basically compiles to this, window.livewire.find. So it's finding the root element for your component, and then it's calling entangle on that. And that's it, magically behind the scenes, everything will work. Which means if we were to take a look at this, don't forget, I can always do $0 to fetch whatever element is currently selected in the inspector.
I can always do $0 to fetch whatever element is currently selected in the inspector. So anyways, I could say, let's grab that Alpine object, go to the data, and set show, or view show, and it is set to true. But if I get rid of it, and I run it again, it disappears. We don't have access to it. And that's because if we switch back, we had this thing going on here, where we only rendered the modal if this property was set to true. So why don't we go ahead and remove that now, and if I come on back, let's give it another go.
Toggling modal with x-show3:36
So why don't we go ahead and remove that now, and if I come on back, let's give it another go. You'll see, actually, as I refresh, it's always showing now. So if we were to take a look at this, once again, do what I did before, it's set to false, and yet I still see it here. All right, well, that's because we show the confirmation modal here, and there's nothing that says, well, render this based upon that value. So now we can do it with Alpine, x-show equals show. Only show this div if this source of truth, this model, effectively, is set to true.
Only show this div if this source of truth, this model, effectively, is set to true. So now if I give it a run, it shouldn't appear, and it doesn't. Give it a run, and that's set to false. But now, when I click on this, if we run it again, it's set to true. Kind of cool, right? So think about it, think about what's going on here. If I come on back, when we clicked Yes, Delete, we updated show model on the server. However, our modal is syncing that value.
we updated Show model on the server. However, our modal is syncing that value. That's the power here, it's really cool. And also, think about it, if I were to, let's open this again, have a look here. All right, so I'm going to set show to false. And when I do this, we should see a network request come in, even though I'm changing it on the Alpine frontend side. So we run it, it disappears, and there's our network request. And again, this is all because of that entangled directive. I almost think the directive should be called sync, S-Y-N-C, but
Avoid hardcoded model names6:21
We disappeared this. One more time, hit escape, there we go. You're still getting that network request. So there is one option you might consider, but we'll get to that in just a minute. So if I come back, I said we were going to talk about why writing show model here isn't ideal. Think about it. This is a confirmation modal Blade component that can be used anywhere. And actually, real quick, let's put all of these on their own line.
This is a confirmation modal Blade component that can be used anywhere. And actually, real quick, let's put all of these on their own line. This is how I would normally structure it. Anyways, this is meant to be used anywhere, regardless of the Livewire component or the php file it's contained in. However, to use it, it's now assumed that there's a show model property available to the Livewire component. But what if your particular Livewire component has something like confirm, and that controls the state of the modal, or even just show, or show, delete, user? Maybe you name it differently from Livewire component to Livewire component.
and that controls the state of the modal, or even just show, or delete, user? Maybe you name it differently from Livewire component to Livewire component. Well, the problem is right now, we are forcing that property to be called showModel. Okay, so we want to make this more dynamic, and here's how. If I, well, first, let's bring this back to what we had before, okay. If we come back here, we can say wire:model here, and the name of the property is showModel. Okay, basic Livewire model stuff here. But now, we can fetch this from the Blade component, which is really neat. So right here, instead of hard coding showModel,
Reading wire:model from attributes7:43
But now, we can fetch this from the Blade component, which is really neat. So right here, instead of hard coding showModel, we're going to use attributes wire:model. Okay, so this might be a little confusing, because there's a few moving pieces here. This is a Blade component, don't forget. And if you're familiar with Blade components, you know that there's an attributes variable available to it. And that will contain everything that's not a prop that you pass as an attribute to the Blade tag, effectively.
And that will contain everything that's not a prop that you pass as an attribute to the Blade tag, effectively. However, on top of that, Livewire extends that to offer a wire method so that you can fetch things directly off of a Livewire attribute, or whatever the term might be. So for example, you have things like wire:loading, or things like that. If it begins with wire, you can access it with that wire method. So in our case, I know I'm not being super clear here, but in our case, when we say attributes wire, we're saying, all right, get a wire attribute. And specifically, we want the model here.
when we say attributes wire, we're saying, all right, get a wire attribute. And specifically, we want the model here. So that will give us this. And that simply gives us a way to pass this Livewire key to the Blade component, and it makes it a little more flexible and portable. All right, let's see if we're still on track here. We run it, and it works. Let's click outside. Let's hit the Escape key. Everything is working here.
Deferring network requests9:05
Let's hit the Escape key. Everything is working here. But again, notice, you do get those repeated network requests. So one way around this, like we've touched upon a bit, is to delay or defer the network request. So for example, if we change the state here with Alpine, do we immediately need to update the server by immediately making a network request? And if the answer is no, then we can defer it easily by simply adding model.defer. And now we will only sync that up as part of the next forced network request,
And if the answer is no, then we can defer it easily by simply adding model.defer. And now we will only sync that up as part of the next forced network request, whether you do something like this or you submit a form. But if you're just changing the state on the Alpine end, it shouldn't make the network request. So let's give it a shot. We run it here, and we get that initial request. That's fine. But now when I close it on the front end side, notice it doesn't make that second request.
your usage of Confirmation model now comes with the expectation that you know what's going on in there, that you know that Confirmation model is an Alpine component. It does have a show property, and you are able to manipulate that. So that's not ideal. And then second, you're going to end up in this situation where you have Alpine usage mixed in with Livewire usage. There's nothing wrong with that, but it gets tricky. So for example, I could also write this as x-on:click. Yeah, so you'll end up with things like this, where it's like wire:click,
So for example, I could also write this as X on click. Yeah, so you'll end up with things like this, where it's like wire:click, X on click, what's the difference? Why are we doing Livewire here and Alpine there? It gets tricky very quickly. So these are all things you may want to keep in mind. Just because this removes that second network request when you click Cancel, doesn't mean it's necessarily better. I would still probably stick with this approach, because it is blind to the fact that confirmation model uses
I would still probably stick with this approach, because it is blind to the fact that confirmation model uses Alpine behind the scenes completely. So notice right here, there's no reference to Alpine at all. Alpine is now isolated within the Blade component. So yeah, these are all the things to think about and how it gets a little tricky if you're not careful. Because if you think about it, this is an Alpine component that is part of a Blade component that is referenced within a Livewire component. So there's a lot of pieces here, and
that is part of a Blade component that is referenced within a Livewire component. So there's a lot of pieces here, and you want to make sure you organize them as best as you can. Because at the end of the day, what we want is to make it as easy as possible to use, in this case, a modal component. Okay, but we're making pretty good progress. We've now introduced Alpine. We've reviewed this nice entangle directive that's part of Livewire 2. We now handle closing the modal when you click outside of it or you press the Escape key.
