Django and HTMX #8 - Infinite Scroll and the hx-push-url attribute

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi there in this video we're going to look at two new things in htmlx we're going to look at the hx push url which will allow us to change the url when we load up new partials and we're also going to look at how to do pagination and infinite scroll using htmx to change the url we can see that when we click to this detail view the url changes and when we go back it changes back we're going to see how to do that and you can see that by default if i look at this page we get 20 elements and we can implement infinite scroll to keep loading up new sections of this page for as long as there's content so let's dive into the code and see how to do this now so let's start by adding an hx push url attribute to allow us to change the url when we go from the list page that you see here to the detail page now currently as you can see that doesn't happen we go to the detail page it's the same url and when we go back so let's get started by looking at the film list component and it's this anchor tag here that we're going to target this this is what actually loads the detail view into our page so we can add an hx push url to this and we can specify what is the url we want to actually push to the browser history so it's going to be slash films and then we want the actual name of the film to be in the browser's url so we'll put film.film.name in there and now you should see that this actually hooks it up so when we click pulp fiction you see that that appears in the url within our browser same if we click escape from new york you see that that appears but one problem we've got is that when we go from the detail page back we still have that in the url so we need to do it the other way as well so if we go to film detail i'm going to copy this attribute film detail and it's this button that we click here that takes us back to the list page so we need to add hx push url here and this is just going to go to slash films so if we reload this page we need to go back to the slash films let's say no country for old men we see that appear in the url we go back and it's gone so we're now able to go between the the list page and the detail page the url changes so it makes it look like there's actually another page being loaded in so this kind of replicates react router functionality and react or view router and this gives you a nice way to do this with htmx very easy and that's there's more you can do and it works by interacting with the browser history object but that's all we want to cover in this tutorial let's now move on to infinite scroll so as you can see i've generated a lot of films here these have just got random names and with six characters i just did a bit of code in the django shell to generate these but what we have here is 126 films basically and we want to paginate this and use infinite scroll to load up more components or more films rather so let's say if we wanted to paginate it by 20 we want to hit the 20th film and then htmx should dynamically send a request to get the next 20 films so what we're going to do is wire that up in this video so the first thing to do is we want to go to our views.pi and we have this film list that's responsible for rendering this page here it's very easy in django to paginate a list view and you just need to add an attribute to the actual class as you can see in this page here so paginating a list view the attributes called paginate by and we just specify a number that's the number we want to paginate by so very simple to do that one thing i'm going to do is update the model because this is now a user films um list view essentially but what we can do is add a page in 8 by attribute and we're going to set that to 20. now this might normally come from your settings.pi or you might set a variable somewhere that determines how much your page you're eating by let's just hard code it for now and if we go back to our list view you should see now that we only have 20 films on the page and that's because we're applying this pagination now the question we've got is how do we set up infinite scrolls so if we go along to the htmx documentation they have a page dedicated to this and as you can see there's a table row element with some data now what the the jester infinite scroll is when you get to the bottom of the table you should dynamically load up more data as you can see there now you the way to do this is we're going to wire up an hx get request so i get request to this particular url um that's what's happening here and then this is the important part it's the trigger um it's going to be triggered on the revealed event now the revealed event is kind of a special event that um will will fire when you get to the end of a current list essentially and it will load up the next set of data and then it will swap it into the dom after the end of the target so these htmlx attributes should only be applied to the last element in a list of data and then when it returns new html data it should have this applied to the last element in that data as well so you can do this infinite scroll pattern using these attributes now how do we do this in our code let's dive into that now i think what's important to note is that we're always going to be returning more elements in a for loop so if you look at what we've got now we have this for loop of films and the film list.html what i'm going to do is actually move that i'm going to move that into its dedicated a dedicated partial which i've already created film list elements let's paste that in there and save that so basically this elements file will be responsible for iterating over the films that we've got in our context and rendering them out now i want to include that partial here and i'm just going to include it using the django template tag and it's going to be partials film list elements dot html so that should include that let's check that that still works on the front end and we do still get 20 films being rendered so the partial is now working now what we need to do is um we need to set up in our film list elements we need to have the last of these devs that represent a film so for each film we're rendering out a div which is basically each line in this list we need to wire up for the last one only um the ability for hdmx and django to return new data that's then swapped into the dom so what we need to do is in the last iteration of this template for loop we need to set htm x attributes to fetch the new data so let's see how to do that now what we actually need to do is django templates provide this um construct called for loop dot last which tells you when you're in the last iteration of a for loop within a template and we're going to use that here in order to set up the htmx attributes if we're in the last um iteration of that for loop otherwise we're just going to set a normal div that we've got here so all we're going to do is we're setting these attributes on a div so only on the last iteration of that for loop should we do anything other than just an empty div so the question is what do we actually add to this for loop so let's copy the div element and we're going to set up an hx get request now the url we're going to send this to is the film list url so we already have a film list and if you look at the urls.pi the film list is actually the class-based view that we're paginating okay so within views.pi it's this film list that we've said paginate by 20. now by default we return this template called films.html what we want to do is if we're in the infinite scroll via htmx we want to return the partial instead with the next 20 films in our list so we're going to see how to change the template that we're returning in a second but for now let's go back to our film list elements and finish this htmx component here the the attributes that we need to add so we're going to send it to the film list element and the trigger is going to be revealed as we specified in the documentation or as we've seen in the documentation rather and we're going to swap the returned response and after the end of the current response and i'm going to set the hx target to be this which means it will be applied to this particular element so let's now see what happens now this this url is not complete because we need to actually send what page we're on so that the back end knows what are the next 20 elements to render you can see a bit more about this in this documentation here basically when we paginate this data we're going to send we need to get the page number now we're going to do that through request.get but we'll see that in a second now we've wired up this here this is only applied on the last iteration so now let's add django htmlx to our project so you can use the pip install command django htmx and once that's installed what we're going to do is we're going to cross to views.pi now we're going to use django hdmx to help us out a bit here if it's an htm x request for the infinite scroll coming into this view what we want to do is we want to return a different template we want to return the partial template with the next 20 films this is a class-based view and one of the methods you can override is get template names and it's got a bit of auto-completion here but basically what this is going to do is under normal circumstances we want to just return films.html so i'm just going to add that here return films.html otherwise what we're going to do is we're going to use something provided to us by django htmx now there may be other ways of doing this but i found this to be quite simple and i'm trying to learn about django hdmx myself so it's a package by adam chains and you can see that what you need to do is add a few things to installed apps and the middleware settings but basically the main thing it provides you that i'm going to use is that this middleware appends or adds an htmx attribute to the django request object and you can use that as we're about to do to return a different template in the case of a request coming from hdmx so let's add django htmlx to our installed apps we need to go to settings.pi for that so in settings.pi we're going to add it at the bottom here and we need to also add the middleware so we'll grab this middleware here and we can add that to the settings middleware settings i'm just going to fire it in here and there's absolutely no logic to where i've put that probably it could be at the bottom but let's just stick it in there and what we're going to do now is we're going to go back to our views.pi and we're going to now use the fact that we now have an htmx attribute on a request object so if self.request and for anyone that doesn't know in a class-based view you have the self um argument as a first parameter and you can get the request object through self.request and we know now that the middleware will add an htmx attribute this is a boolean it's true if the request comes from htmx so if that's true i want to return the partial and that's going to be partial film list elements dot html otherwise let's just return the normal template now the final step is to we need to tell this list view what page we're on we've got a paginate by but we need to now tell it what page to look for next so within our film list elements we can add some attributes to the url to do this now i'm going to cross back to the django documentation here this will all be linked in the description but um let's let's see what i mean here so in the documentation here if you look up here at the the paginate in a list view section this is the template code and we can see a few things that we can use now the pagination utilities in django you they add a page object to your template and you can use this to get the page number that you're on at the moment so let's say at the beginning it's page one we are now wanting to attach a get parameter that will tell the url and the get parameters done like this we want to make it the current page number plus one and we want to send that to the viewer that's basically all we need to do in a list view here so if i add a page attribute to the url this is a url query parameter all we need to do is set that to the page object that the listview will automatically put in our template pageobject.number and we use a template filter called add and we're going to add one to that we get the page object that we're on let's say one and then we add one to that so then we will send the request with the page equals two to get the next set of data and then when we get back that data we will have page two and then the next one will load the data for page three and basically django's views the the list view with this paginate by this will take care of all the logic for you of um amending the query set to get the right elements so that's quite useful let's see now if we can run the server and test this out we cross to the page and we reload we are getting an error here so invalid block on line four looking at this error here i've missed out the url template tag within this template so let's go back to film list elements and we'll add the url template tag and we need to wrap the name of the url in the quotes so let's try that again and we get back 20 l and you can see now this is actually working um so if i refresh the page by default we get 20 elements but if i scroll down to the 20th you see we stop here but then very quickly we're reloading the data and if you look at the back end here you can see that we're getting these get requests coming in and the page numbers are incrementing by one each time we scroll down so that's basically it that's how you implement infinite scroll and htmlx and django you can use the pagination utilities to do that and when we scroll down past 260 we're going to load the next 20 elements so we get down to 80 and so on until the end of the list so easy enough to do that in django especially with these utilities provided by the list view the pagination is very easy and we use django htmx that extension to make things a little bit simpler in terms of determining which partial to return now there are going to be a few things are broken in this application now because the pagination is not going to work for example when we go back from the detail view to the list view because by default that's loading everything maybe this is an exercise for the the viewer if you want to try and fix all of this i think the the main thing for this video is to get across how to implement infinite scroll using django and htmx using pagination and the template utilities that django provides as well makes it very easy to determine when you're at the end of a list of elements where you can then attach the htmx attributes you need to get the next set of elements so i think that will cover everything for this video thank you for watching if you've learned anything or enjoyed the video please like and subscribe and we'll see you in the next video
Info
Channel: BugBytes
Views: 379
Rating: undefined out of 5
Keywords:
Id: RacU_1NgVIg
Channel Id: undefined
Length: 14min 48sec (888 seconds)
Published: Mon Nov 15 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.