Simulating Like Latency0:00
Okay, let's finish up the implementation of a like toggle by bringing the pending states back. Okay, so the first thing I want to do to be able to work on the pending state is actually add some latency to our like functionality. So here I can do that with the sleep function. And let's sleep for a good three seconds. Again, this comes out of the box in Laravel and it's super handy when working on pending UIs. Alright, so now let's go.
and it's super handy when working on pending UIs. Alright, so now let's go. And unlike a puppy, I am so sorry Russ, but I will unlike you, although I love you, but check this out, I'm going to click 1, 2, 3, and after three seconds the state is going to change. Let's do that again. I'm going to click now 1, 2, 3 and the heart should come back. So I don't know if the latency is ever going to be three seconds long,
So I don't know if the latency is ever going to be three seconds long, but let's assume that it can, it might be even longer. And this sort of UI is very rage click inducing. You click on the button, nothing happens. You click, click, click, click, click, click, click click, click click. And so the last thing we want is to make our user rage. We want them to be very happy. After all, this is an application about liking puppies.
Restoring Pending UI1:23
We want them to be very happy. After all, this is an application about liking puppies. You should never rage when you're in the context of liking puppies. So let's bring a delightful pending UI with the loading spinner back so that everyone remains calm and happy. Okay, so originally in our implementation we had a pending state that was manually toggled on and off at the start and the end of the interaction.
Using Inertia Data-Loading1:47
state that was manually toggled on and off at the start and the end of the interaction. And we could do this, but let's inspect one of the button elements here. So the button here and look at what happens while the action is happening. I'm going to click and you can see this data-loading attribute that will then disappear. Let me show you one more time. I click and the button has a data-loading attribute while
Let me show you one more time. I click and the button has a data loading attribute while it's pending and then it goes away. Alright, so check this out. We can do some pretty cool fancy CSS here, uh, especially with Tailwind CSS. So I'm going to get rid completely of the pending state here. So we don't need useState at all in the component anymore. Very cool. And here, instead of using pending uh,
So we don't need use state at all in the component anymore. Very cool. And here, instead of using pending uh, and have a ternary operator, I will remove the ternary and keep both elements. So at this point it's not going to look great. And you can see we're going to have both icons for every card stacked on top of each other. But now is where we get clever for the lotus circle. I will set it to hidden, which is display: none;. So now it's not showing anymore.
I will set it to hidden, which is display none. So now it's not showing anymore. And if the button has a data-loading, we wanna display it to block. But this is not going to work just yet. Maybe you can work out why, but let me show you that it doesn't. If I toggle a like nothing happens. Oh, and by the way you can see that little progress line here.
Customizing Progress Bar3:12
Oh, and by the way you can see that little progress line here. Before I mentioned that no UI changes was happening, but you can see that there is some sort of feedback happening here with that little line. And you can customize the color of this if you want. This happens in app.tsx here where we create the inertia app, there is a progress color. So if you wanted to make this a nice blue, let's use that color.
So if you wanted to make this a nice blue, let's use that color. So what is a puppy foam button color? This is a side quest but it's very worth it. So here ring 500, huh? I don't know. We can pass the CSS variable directly. Let's try that. Actually with a bit of luck we might be able to use the CSS variable here and let's try to like a puppy and yeah, it's working. Very cool. So now we have this on-brand uh,
and yeah, it's working. Very cool. So now we have this on-brand uh, loading state line. But to get back to what we were talking about, uh, you can see that nothing happens. The loading spinner is not showing. And so you tell me the reason because I know that you know, do you, well the data-loading attribute is not on the SVG icon, the heart itself, but it's on the button.
Group Selectors for Spinner4:14
well the data loading attribute is not on the SVG icon, the heart itself, but it's on the button element, which is the parent. Luckily the parent has a group class already that we are using. So we can use group data loading to make the selector that we exactly want to target. I told you we were gonna get fancy. So there is the group here and we can do group-data-loading and look at this.
So there is the group here and we can do group - data loading and look at this. It's going to check for group and then data loading, which is exactly what we trying to achieve. And so now when I toggle a puppy like Rex, the spinner is showing while it's loading and then it goes away. That's pretty cool, right? And so now instead of having our own pending states
That's pretty cool, right? And so now instead of having our own pending states that we have to start at the start and stop at the end, we can use the Inertia's internal data loading attributes on the link tag. And with a bit of clever CSS, we can do the adjustments of what shows and what doesn't while the data loading attribute is on. So let's finish it up by making the heart not show when the
loading attribute is on. So let's finish it up by making the heart not show when the button has the data loading attributes turned on. Alright, so here we hide unless there is the group data-loading. And I'll copy this group data-loading class. And here we are going to do the opposite. Uh, so I'll use clsx one more time here and we'll have this as the first condition. And so I can have a second condition here.
and we'll have this as the first condition. And so I can have a second condition here. So the second item we're gonna pass to CL LSX is that class of groupDataLoading. And if so, we're going to set display to hidden, which really is display: none, but the class name is hidden. So we keep the same logic of whether to show the pink heart or the empty heart. But then we also say, hey, if your groupParent has a dataLoading
But then we also say, hey, if your group parent has a data loading attribute, then hide yourself. And so that combination right there of hiding the loading circle and hiding the heart alternatively, based on the data loading attribute is all we need to have a CSS only implementation of a pending state. I think that is pretty cool. Alright, so let's check it in its final form.
I think that is pretty cool. Alright, so let's check it in its final form. I'm going to, unlike BellaSpinner and the response come back and same with LunaSpinner until the response comes back. Come on. That is pretty cool, isn't it? We have replaced a full-on asynchronous data fetching to an external API with a link tag. Literally it translates to a button,
with a link tag. Literally it translates to a button, but we literally having a link that submits a PATCH request to a specific, uh, route in our routes and then it does the change with the like toggle and then returns back to the same page. We have the pending state integrated with it. How cool is this? And it's really, really, really simplified a lot of stuff. So I hope you enjoyed this
Refactoring to Index Route6:58
And it's really, really, really simplified a lot of stuff. So I hope you enjoyed this and you see the power of pairing React with Laravel through Inertia. And because that lesson was quite short in comparison to the previous one, what I want to do is go in web.php and you know how we've created a PuppyController here with the like method. Well if you think now we have a PuppyController and really this homepage is showing all the puppies.
Well if you think now we have a PuppyController and really this homepage is showing all the puppies. And so if you think about it in terms of convention, these listing all the puppies is the index method. The index action on the puppies resource. So let's move this uh, home route into the PuppyController's index method to finish it up. So I will grab all the contents of this home route and instead of having a function here, I'm going to offload this to the PuppyController class.
and instead of having a function here, I'm going to offload this to the PuppyController class. And we are going to pass the index method so that index method doesn't exist. And as a result we have blasted our app, but fear not. I can go in the PuppyController and add a public function index and here I can paste whatever was in the function. So I'll need to import Inertia and I'll need to import the PuppyResource.
So I'll need to import Inertia and I'll need to import the Puppy resource and an app is going to work again. And maybe another thing that I would do is go in the resources/js/pages and instead of having this called welcome, I will create a new file or folder and file and the folder will be puppies and then index.tsx. So I will copy everything in there and put it inside of there instead.
So I will copy everything in there and put it inside of there instead. And I will delete the welcome.tsx file. And so here instead I will render the puppies/index, which really mirrors the PuppyController's index method, which I think is a great convention. And the last bit of cleanup we can do perhaps in web.php is get rid of the puppy and puppyResource that we don't need anymore, 'cause this has moved to the PuppyController.
and puppy resource that we don't need anymore. 'cause this has moved to the PuppyController. So we have a homepage here which points to the PuppiesController@index. And then we have our logged in routes below. And I think this is nice and clean. Okay, we had a couple of side quests in this lesson, but because it's a slightly shorter video, I think that was a pretty good time to make this quest. Alright, I will see you in the next video.
that was a pretty good time to make this quest. Alright, I will see you in the next video.
