Back Button Expectations0:00
Like it or not, users expect our web applications to behave like web pages. And really when AJAX became mainstream, the idea was to create these experiences that users expected from desktop applications, which sounded good at the time, but ultimately, because by the time AJAX was mainstream, users had already adapted to this whole internet thing. They fired up a browser, went to a webpage, clicked on links, but most importantly, they clicked on that back button to go back. And early on,
but most importantly, they clicked on that back button to go back. And early on, that was something that our applications just couldn't do and thankfully they can now. It really doesn't matter what framework or tools you use. The ability to go back is built in. HTMX is no different. So we have this application where if we go to the index, we of course see our snapshots. We can go to open invoices. We can go to approved invoices, but from a user standpoint, they would think, well, I'm at approved invoices.
Adding hx-push-url1:05
We can go to approved invoices, but from a User standpoint, they would think, well, I'm at approved invoices. I want to go back to open invoices. So they'll click on back thinking that it'll take them back to the open invoices and it doesn't. And as a user, that's frustrating because, especially if there was a lot of things that had changed, then they have to go forward again. And it's just frustrating. So what we can do on our end is inside of our index view where we have our snapshots and we have those links to load those invoices. We can add another attribute. It's called hx-push-url.
snapshots and we have those links to load those invoices. We can add another attribute. It's called HX push URL. We will set this to true and we will add it to both of these links. Now this is going to do a couple of things. First of all, it's going to push the request URL into the browser's navigation bar. So when we click on this link, in fact, we can go ahead and do that. Let's click on open invoices. We will see that the URL is now invoices/open. If we click on approved invoices,
We will see that the URL is now invoices/open. If we click on approved invoices, the URL is invoices/approved and logically we could think we could click on the back button to go back to the open invoices and sure enough we can. So that's the first thing that this attribute is going to do behind the scenes. HTMX is also going to cache the response. So whenever we go back, it's going to load that cached response back into the browser unless if the cache is invalidated or it's cleared for whatever reason, which would happen, which that can cause a problem because now we have this URL invoices/open.
Handling Direct URL Loads2:36
is invalidated or it's cleared for whatever reason, which would happen, which that can cause a problem because now we have this URL invoices/open. And what happens if we just go straight to that URL without going to the index? Well, we see our list of invoices, but we lose the snapshots. So when it comes to building modern web applications with something like HTMX, we need to be consistent with what we return from the server. It doesn't matter what kind of requests it is. If it's a fresh request by a user typing something into the navigation bar or if it is dynamically loading contents by the user clicking on links that are making HTMX requests.
Extracting Snapshots Component3:13
it is dynamically loading contents by the user clicking on links that are making HTMX requests. So what we need to do here for our open and approved invoices, we need to include those snapshots. Now the way I have designed this, we just need to make a few changes to make all of that work. The first thing however, is we need to extract this section that has our snapshots because we want to be able to include that section inside of our list view where we show our list of invoices.
able to include that section inside of our list view where we show our list of invoices. So I'm going to create a new component called snapshots.blade.php. So we will have snapshots and then we will have snapshot to display individual snapshots. But now that we have broken that out into its own component, that means that inside of the index we can refer to that with a new component. With x-snapshots and we can essentially do the same thing inside of our list view. So let's just copy and paste.
view. So let's just copy and paste. We want this defined outside of our fragment for the invoice list, but then we need to go to our AppServiceProvider because I've used composer to automatically provide the model for what was the invoices index view, which for all intents and purposes was just the snapshots. So now I need to change this to components.snapshots and that's going to take care of some of it. So let's refresh. We will still have our snapshots inside of just the plain invoices index,
So let's refresh. We will still have our snapshots inside of just the plain invoices index, but whenever we go to the open invoices or the approved invoices, we see that those are still loaded. If we go to the actual URL, those invoices are loaded as well. However, let's clear out one of these approved invoices. So this one right here with invoice number PXI212244, if we submit this, it is going to submit that invoice. But if you notice the snapshot didn't change.
Updating Multiple Fragments5:14
if we submit this, it is going to submit that invoice. But if you notice the snapshot didn't change. Whereas if we are just in the invoices view and we submit one, we will see that the snapshot will not update. Okay, I lied. And that makes sense because we are at invoices/approved now. So this is an issue that we need to fix, but thankfully it is very easy to do. We just need to go to our InvoiceController and now we don't really need to worry about including this fragment for our snapshots when the current URL is our index because now for all intents and purposes, we will never be at the index whenever we submit the form.
our index because now for all intents and purposes, we will never be at the index whenever we submit the form. So really we can get rid of this, but now we have the snapshots fragment inside of our invoices list. So we need to modify this so that instead of specifying a single fragment, we could specify multiple fragments like that. But this also kind of changes the context of addFragment that makes you think that you're only going to add a single fragment. So let's keep that addFragment in case if we ever need it. But now we need an addFragments.
So let's keep that ad fragment in case if we ever need it. But now we need an ad fragments. So let's open up the HTMXResponse class. Let's copy our adFragments method, paste that copy and we'll just make a few changes. We'll change the name to addFragments. Now we have an array of fragments and then whenever we call the fragment method off of the view, well we will just call fragments, pass in the fragments and that should work so we can go back to the browser. Let's refresh for good measure, although we probably shouldn't need to.
pass in the fragments and that should work so we can go back to the browser. Let's refresh for good measure, although we probably shouldn't need to. And let's try this again. So we have an approved invoices count of 261. If we submit one of these, that should change and sure enough it does. If we go to the open invoices, let's select this one and now our open invoices count should change to 134. The approved invoices count should change to 261. So as you are developing your application, it's always important to think about how users are going to navigate through your application.
Navigation Consistency Guidelines7:23
it's always important to think about how users are going to navigate through your application. It's very easy to get into a rut and think the user is just going to click on whatever links that they need to get to go wherever they need to go and yeah, but they'll also use the back button, the forward button. They'll type URLs into the navigation bar and head in there and expect that page to come up. So just be consistent. It doesn't matter how the user actually gets to whatever page in your application you need to provide the actual content. So if it's a fresh request,
application you need to provide the actual content. So if it's a fresh request, be sure to include everything in that first request and then afterwards just, you know, load different fragments here and there. The ultimate goal is to provide an experience where the user doesn't really know that there's really anything special going on behind the scenes. If you can do that, then you're golden.
