Handling non-refresh updates0:00
Okay, let's actually wire this up to our application. So we have two cases, one when it doesn't make a full page refresh and it just updates the DOM accordingly. So those cases are everything here except delete. And the other case is when we do make a full page refresh and redirect. So those cases are for deleteIdea. If you remember, if I click this, it will delete the idea and redirect back to the index page. And I'm also doing a full page refresh on creating an idea here. So let's start with the case where it does not do a full page refresh.
And I'm also doing a full page refresh on creating an Idea here. So let's start with the case where it does not do a full page refresh. So take a look at our component here. And we have this window.livewire.on listener that listens for this event and then acts accordingly. So before we were just using this to close the modal. But in this case, we're in a different Alpine component. And this is for our notification success. So we do want to show it. So for this particular case, idea was updated, it should open it when it hears this event.
So we do want to show it. So for this particular case, Idea was updated, it should open it when it hears this event from Livewire. And if you don't remember, I believe it's called ideaEdit, or editIdea. The class, we are emitting this event from here. So Idea was updated, and then we're listening in here. So this should work. So let's go ahead and update this Idea. And that does not seem to work. Okay, so that doesn't work because the x-init has to be at the root div.
And that does not seem to work. Okay, so that doesn't work because the X init has to be at the root div. So we have this temporary root div because we wanted this button in here. So let's just put in here for now. And that should work. And then we'll remove it after we don't need it anymore. So window.livewire.on idea was updated, it should show this notification component. So let's go ahead and update the idea. Let's remove this change.
So let's go ahead and update the Idea. Let's remove this change. And let's update. And there it is. Cool. Now, it doesn't have that set timeout. And it doesn't disappear automatically because that's set on the click handler for the button. So if you add this, it should work. So let's put it in here. And let's try that again.
So let's put it in here. And let's try that again. So I'm going to hard refresh. Let's update the Idea again, say change. And this should disappear in five seconds. And it does. Cool. So I'm going to get rid of this toggle button now since we don't need it anymore. So now we can put this x-data and x-init on this other div here. And we no longer need this button as well.
So now we can put this X data and X init on this other div here. And we no longer need this button as well. So let's get rid of this. And I think we can get rid of this div here. Okay. So now we should have one root div. Let's make sure that's the case. Okay. And let's paste in the X data and the X init in here. And I'm going to change this window.livewire.on to just livewire.on.
And let's paste in the X data and the X init in here. And I'm going to change this window.livewire.on to just livewire.on. Same thing. Just a bit cleaner in my opinion. So I'm going to change it for the modal as well. So modalConfirm instead of window.livewire.on. I believe that's the only place I'm using it. Yeah. So let's change that to livewire.on, which is the same thing. Okay.
So let's change that to livewire.on, which is the same thing. Okay. So let's confirm that by hard refreshing and changing it again. Let's remove the change. Let's update. It's updated. The notification shows and it should disappear in five seconds. And it does. Cool. Okay.
Adding dynamic messages3:54
Cool. Okay. Now this message is hard coded. And obviously we have different messages for different success messages. So let's go ahead and fix that. So I'm going to remove this. ID was updated successfully. Let's cut that and we'll keep it as a piece of state called message to display. So let's say x text message to display, and this will be dynamic now. So let's add that to our x data message to display.
So let's say $textMessage to display, and this will be dynamic now. So let's add that to our $dataMessage to display. Let's say '' to start. Actually, I'm going to reformat this so it's on its own line. And now in our listener here, we can accept a $message that gets passed in from the Livewire component. So let's accept a $message. Let's set that $message here. So $messageToDisplay is the $message coming in. And for this particular case, so Idea was updated.
So message to display is the message coming in. And for this particular case, so Idea was updated. Let's go back to edit Idea. And when we're emitting the event, we can pass in the message here. Okay. So let's see if this works. Hard refresh, update again, change. And now hopefully this works. And it does. Cool.
Adding spam event listeners5:11
And it does. Cool. So now we're passing in dynamic messages. So now let's handle the other two cases. So that would be markAsSpam and markAsNotSpam. So again, this is a case for where it does not do a full page refresh. So let's go back to our component. And we just have to listen for those new events. So let's duplicate this. So the other one is Idea was marked as spam, I believe.
So let's duplicate this. So the other one is Idea was marked as spam, I believe. Okay. So the message will come in from Livewire and we're doing the same thing here. So we do have some duplication, which we'll clean up in a second. Let's just add the other one too. So we can see everything working. So Idea was marked as not spam is the other event name. And let's just pass in the appropriate message. So mark as spam, let's pass in the message here.
And let's just pass in the appropriate message. So mark as spam, let's pass in the message here. Idea was marked as spam. Okay. And for the other one, mark Idea as not spam. Let's say spamCounter was reset. That's fine. Okay. And now let's see if that works. So hard refresh.
And now let's see if that works. So hard refresh. Let's try markAsSpam. Yes. Okay. Idea was marked as spam. And let's also try the other case. Not spam. Reset spam counter. And it does work cool.
Refactoring duplicate logic6:50
Reset spam counter. And it does work cool. So let's clean up that duplicate code that we have. So back to our component. And we want to extract all of this to a method. So there are a few ways to do this in Alpine. But since this is not too long, I'm just going to do it directly in our x-data here. So up here, let's make a new method called showNotificationMessage, or showNotification is fine. And we'll pass in the message.
is fine. And we'll pass in the message. And this will be a method. And we can paste that in. So let me just grab this, paste that in. But now if we're referring to other state, in this case, we are we have to refer to it using this. So let's do this. Okay. And in here as well.
Okay. And in here as well. And now we can replace all of this. Let me just grab these three. Okay, let's grab all of this. And it's called that method. So showNotification. And we're passing in the specific message for each event here. Okay, let's see if that still works. Hard refresh.
Handling redirect flash messages8:31
Okay. And let's try resetting the spam counter as well. Not spam. And it does work. Cool. Okay, now let's handle the two cases when we are making a full page refresh or a redirect. And that's when we're deleting the Idea or creating a new Idea. So deleting an Idea will redirect back to the index page. And same for adding an Idea. So let's handle those cases.
And same for adding an Idea. So let's handle those cases. So for now, I'm just going to copy this or everything in here, actually. And let's go to our create.blade.php. And we don't need this anymore. So let me just comment it out for now. And I would paste it in here. But I'm going to change it so that the message doesn't appear here. But in the app.blade.php. It would still work if it's in here, because the create Idea is on both pages.
But in the app layout, app.blade.php. It would still work if it's in here, because the createIdea is on both pages. But let's just put it here anyways, makes more sense. So let's just paste it in here after the main element. And let's see what we get here. Let's make a few changes here. So let's say true, just so we can see it rendering. And let's set something in here, say fullBar for now. Okay, so let's go to the index page. And you can see it render out here.
Okay, so let's go to the index page. And you can see it render out here. Okay. But for full page refreshes, we can't make use of events because there's a full page refresh going on, and it can't listen for events. But we can make use of the flash messages. So same thing as what we did in here, we're listening for the session variable called successMessage, and then showing that message if it exists. So let's do something similar. Let's grab this, and we'll test it out on the creating of Ideas.
So let's do something similar. Let's grab this, and we'll test it out on the creating of Ideas. So we'll wrap this entire div in that check if the session variable exists. So let's add this, close it out here, sorry, and if and we don't need these anymore, because this comes from the other case where we don't make a full page refresh, we'll grab the initial message from the session variable. So instead of hard coding this, we can say, session success message. So let's do that. And let's just paste that in and get rid of the if, okay. And let's see if this actually works.
And let's just paste that in and get rid of the if, okay. And let's see if this actually works. So let's go ahead and refresh. Let's add an Idea. And let's see if we get anything. So let's add gibberish here. And this is still showing that I removed that I did not save it, but it still didn't work. Oh, yeah, that's because we have to actually call our showNotification message. So we'll do that here, showNotification, and we want to show the message to display. And that's already populated with the correct session variable.
in from the right. And as you can see, it just kind of appears. So we don't want that. We do want the transition to occur. So I think if we do a setTimeout here, that should fix the problem. So let's try that out. So I'm going to wrap this showNotification in a setTimeout. So setTimeout, callback, and then let's say 200 milliseconds. After 200 milliseconds, run this. So hopefully that works.
After 200 milliseconds, run this. So hopefully that works. So let me hard refresh, let's try again. And keep your eye on the bottom right, see if it slides in. And it looks like it doesn't. Did I not save it? Okay, I think it's not working because we have to set isOpen to false initially. So let's try that again. So after we init, we have a setTimeout for 200 milliseconds, just so the transition does show.
have been made. So I reach for this whenever I have some sort of rendering issue. And let's try that out now. So instead of setTimeout, let's do nextTick, pass in a callback. Actually, we don't even need this. We'll do it in one line. And let's just do showNotification. And let's see if that works instead of the setTimeout. So let's hard refresh a few times. Okay, nextTick works.
Creating reusable Blade component13:58
So let's hard refresh a few times. Okay, nextTick works. And let's keep an eye out on the bottom right. Okay, so it does work. So we'll stick to this solution instead. Okay, so now instead of pasting this code in, I only made a few changes here. So let's go ahead and modify our Blade component and make it dynamic. So let's accept some props up here at the top, like we did for our model. So say props. Let's give it two of the props that we changed for our fullPageRefresh case.
So say props. Let's give it two of the props that we changed for our fullPageRefresh case. So we have to check if it's a fullPageRefresh or not. And I'll name that prop redirect. So fullPageRefresh is a redirect. And we'll default that to false. Okay, and now the other prop we want to accept is the message to display. So in the case when it is a fullPageRefresh, it's going to come from the session variable. But if not, then it comes from the event from Livewire.
it's going to come from the session variable. But if not, then it comes from the event from Livewire. So in this case, we'll just default it to an empty string. So these two cases are for when it's not a fullPageRefresh. So we don't have to specify these props if it's not. So let's add the message to display in here. So say message to display. So it's an empty string when it's not a redirect component. So that's fine. But when it is a redirect component,
So that's fine. But when it is a redirect component, then it will populate this with the correct message. Actually, before we use this, let me just show you the delete case working. So it's still in here. I didn't delete it yet. And it's looking for this session variable called successMessage. And if you look at our CreateIdea class, you'll see that I set the flash message here. And let me just change this to a exclamation mark. And we can do the same for our DeleteIdea.
And let me just change this to a exclamation mark. And we can do the same for our deleteIdea. So deleteIdea. Right before we redirect, let's flash that message. Idea was deleted successfully. OK. And let's see if this works. So let's delete this one. And keep an eye on the bottom right. And Idea was deleted successfully.
And keep an eye on the bottom right. And Idea was deleted successfully. OK. So back to the component. Let's make it dynamic. OK. So we're accepting the message. So that's one of the changes that we made. The other change that we made is in here. So if it's a redirect component, so let's handle that case. Then we want to do what we did in here. So let's grab that code.
Then we want to do what we did in here. So let's grab that code. So if redirect, OK, then we want to do this. Else, we just want to do whatever's in here and listen for these events. OK. And if I did that correctly, that should work, hopefully. So now let's change our code here. Instead of pasting all of this code in, let's get rid of all of this and just use the Blade component.
Instead of pasting all of this code in, let's get rid of all of this and just use the Blade component. So if there is a success message in the session, then we want to render that component, but with those props. So redirect is true. That's why I named the prop to determine if it's a full page refresh component. And in this case, it's true. OK. And we also want to specify the message in here.
OK. And we also want to specify the message in here. So message to display is what I named the prop, if I remember correctly. OK. And that's just the session variable. So we can just do this and grab it from here. OK. Paste that in. And let's make sure to close that out.
Paste that in. And let's make sure to close that out. OK. So I think I forgot a closing bracket here. And now let's see if this still works. So creating Idea, testing. OK, still works. Let's try deleting ideas. And that does work. Let's try the other case.
And that does work. Let's try the other case. So the case when it's not a full page refresh. And this should still work the same because we are accepting default props in our component here. So the definition. So for example, in our show.blade.php, that should remain the same. So this stays the same. Doesn't need any props.
So everything is working. We have one component which doesn't have any duplicate code. Notification success. And it handles both of our cases when it's a full page refresh or when it's not. So as always, let's make a commit here. This is episode 47. git commit -m "episode 47 success message".
