Django with HTMX Tutorial #5 - HTMX Active Search
Key Takeaways
Builds a search bar using HTMX and Django for a contacts app
Full Transcript
all right guys in this video we're going to start using HTM X and we're going to build some search functionality for our contact page so at the moment we have this table of contacts and I've added some contacts for the logged in admin user using the D Jango admin and bonus if you know what these characters reference so we're going to allow users to search through these contacts using HTM X so we're going to build a search bar to start with and note that later in the course we're going to have a form that allows users to add their own contacts but to start with let's use the search functionality and that's going to use the HX get attribute now in order to build the search box what we're going to do is go to di UI components for text inputs and what I'm going to do is scroll down here and we have an example of a text input with an icon inside and here we have a search bar and what I want to do is just basically copy that so we're going to copy this label tag that we have at the top here and that has an input of type text and the placeholder of search here so if we copy that let's add the search just above the table that we see here so in order to do that let's go back to our template contacts. HTML here we're including the contact list table what we're going to do above that is paste in the code here that we've copied from Daisy UI now I want to add a couple of things to this code so we have a label that wraps the input of type text and it has that SVG element and that is for the search icon as well as Gap two what I want to add is a margin bottom of two here and that's going to give it a little bit bit of space between the search input and this table of contacts below and finally one other thing we want to add to the input as well as the type of text and the class of grow and as well as the placeholder is we want to give it a name and I'm going to give it a name of search and basically by giving it a name that means on the server we can look for the value that's been submitted with this name of search and we can extract that and use it to perform the search against the database contacts now before we wire up HTM X let's just go back to application and refresh the page and you can see we have the search bar across the top of the page now now of course you might not want it to span the full length of the page so you can change that if you want I'm just going to leave it as it is for now but of course if we type into this at the moment nothing is happening and that's because there's no functionality attached to this input of type text but what we're going to do now is we're going to use HTM X so that when the user types into this field it's going to send a get request to a search URL in the jangle application now at this point I want to introduce three HTM X attributes the first one is the HX get attribute and that's going to cause an element to issue a get request to a given URL so you can set the value of HX get to a URL where you want to send that get request in response to some kind of event now the event that triggers the request is determined by the HX trigger attribute and these can be standard Dom events such as a click event or a key up event or a mouse over event and for forms it can also be a submit event as some examples and the final attribute for now is the HX Target attribute in HTM X and this is set to an element in the Dom called the target where the response HTML is going to be swapped so those are the first attributes that we're going to work with in HTM X let's go back to VSS code and on the input element we're going to add these attributes so I'm going to split this into new lines just so we can see it more clearly and let's add an HX dget attribute here and what we're going to send a get request to is a URL in the J application and we can use the URL template tag in jangle in order to specify a named URL and the one I'm going to Define in a second is called search after that we can set the trigger so we're on an input element and I'm going to set a trigger of key up basically that means whenever a user types a key it's going to trigger the request to the back end and we'll see how to use a modifier later to prevent overwhelming the server every time a key is pressed and finally we're going to use the final attribute we saw and that's HX Target and we set that to an element in the dome now the element I'm going to set this to is one in this partial that we defined earlier on so this partial contains a div at the top here with an ID of contacts list I'm going to copy that and we reference that using the CSS selector syntax so it's an ID so we use the hash and the name of that ID now the reason that's the target will become clearer later on when we actually hook up the backend functionality in jangle so let's start with that now what we're going to do is create a URL with a name of search to start with so let's go to urls.py and let's copy the path to the line below and we're going to create a new URL called search and the path for that URL is just going to be/ search and it's going to call up a view here called search contacts so now we have this URL path in the application let's go back to the Jango views.py file and we're going to create a new view here and it's going to be the one we referenced called search contact and that'll take the request as a parameter as always in jangle and what we're going to do is we're going to get the search query here we can do that by accessing request.get that's going to contain any properties sent in the get request to the back end and we can use the dog function to extract a key out of that search query so the name of the field in the front end was search and that was referenced here in the name attribute to the input so we're going to try and extract that and if we don't have any value being extracted we're going to default to an empty string here so that's going to be the search query and when we have whatever the user has submitted to the back end we want to use that query to filter the user contacts by name or email so if we go to models.py the contacts are tied to a user have a name and an email address we want to search over those using whatever the user has submitted as the search query so let's create a statement here and what we're going to do to begin with at the top is we're going to import the Q object from django.db Doods now the Q class here as it says in vs code it encapsulates filters as objects that can then be combined logically and you can use logical expressions like and and or in order to combine various Q objects so let's go down and Define the query now and the reason we're using a q object is because we want to allow this to be an or query and that means when we search on the front end let's say with a given name we want to look for contacts that have either a name that contains that query or an email address that contains that search query so let's create a variable here called contacts and we're going to take the request. user and that's the authenticated user and we're going to access the contacts and filter these down so the filter statement is going to take two Q objects the first one is going to look at the name field and it's going to have an i contains expression and we're going to set that to the query that we've extracted on line 15 above and then we can use this pipe operator for the or notation that's going to create an logical or query here and then we're going to look at the email field and again we're going to use I contains and set that to the query so we're going to get back contacts that belong to request. user but we are fill in here to make sure we only get the ones that are associated with this query and that Association is over the name field and the email field and we're using the I contains look up here to perform that query what we're going to do then is just return a render statement in jangle and what we're going to render is a partial template and it's the one we created called context dl. HTML and we can then add a context dictionary here and it's going to have a key of contacts that is set to the contacts that we're pulling out on the line above so this is the view in Jang that's going to respond to that HTM X request we get the search query here on line 15 using the request.get query dictionary and jangle and then we use the value of that to perform The Logical filtering using this statement here and the Q expressions and finally we're rendering contacts list. HTML and we're adding the filtered contacts to the context here now the reason we add this key of contacts if we go to the partial template you can see that it's checking if contacts exist and if they do exist what it's doing is it's creat a table here and it's rendering out each contact and that's what we want we want to take the return contacts from the database based on the search query and we want to return a table that contains those contacts so we're returning a new table after filtering and because we have this HX Target set to the contacts list table when we return this partial here with the same ID it's going to replace that entire table so let's now test this out and go back to our page here I'm going to refresh this page and let's say we're searching for Stanton if we go to the top here and type that into the search bar you can see that nothing is happening now the reason for that if we go back to the terminal here is that you can see that we have a template does not exist error and that's because I've misspelled this it shouldn't be contacts list it should be contact list so let's go back to this render statement here and we're going to change that to the correct name once we've done that we can save this and go back to our application and let's try this again when we search for Stanton Mick you can see that the table filters and we get back the user and that is going to happen dynamically whenever we change this search text here so the key up event is what we're listening for and HDMX sends the get request whenever it receives that event and this will work not only on the name but also on the email field so for example there are two users with an Outlook email address if we search for Outlook here you can see they're both returned and notice that it's case insensitive so we have Joe chip here if we search for Joe you can see we still get that back even though this is a lowercase first letter J and the reason for that is because in the query statements here we're using I contains and that's a case insensitive contains match now notice though that this is going to send requests on every single key up so if we go back to the application here every time we do anything in this field it's sending another request instantly to the Jango server and you can see that here on the terminal it's sending multiple get requests every time that the input field changes now what we can do here is introduce a modifier it's called a trigger modifier in HDMX and that's going to prevent requests being sent every time the user types into the search box now to find out more about trigger modifiers let's go to the HTM X documentation trigger modifiers essentially change the trigger behavior for example if you want the request to happen only once you can use a once modifier and the way to do this is on the HX trigger attribute after you specify the trigger event you can use modifiers after that and some other modifiers you can use include the changed modifier the delay modifier and similarly the throttle modifier and there's also a from modifier as well and some of these take an additional argument now the one that we are interested in here is the delay modifier that's going to wait the given amount of time for example 1 second before it issues the request and the most important part here is that if the event triggers again then that countdown is reset so that means that instead of sending the request every time the user types it's going to wait for a given interval and if we don't receive any more events in that interval it's going to send a request but if we do it's going to reset the countdown and it's not going to send that initial request and that's going to stop the server being overwhelmed whenever the user types anything in so let's introduce that delay now and go back to our contacts list. HTML and in fact this is in contacts. HTML here so the trigger is key up and we can add the modifier of delay and we're going to give it a delay of 500 milliseconds now let's see how this modifies the behavior of the HX trigger element so let's go back back to our page here and I'm going to refresh this page and I'm going to open the developer tools here and go to the network tab so let's do that just now and I'm going to start typing into this box and notice that if I'm typing here we don't send requests on every single key up but instead the request is only sent after the delay of 500 milliseconds has passed and no other events have come in with the key up type so just to reiterate here if we type in something like Gmail here you can see that it's only going to fire those occasionally after 500 milliseconds and same if we type in Yahoo here you can see that it eventually appears but it's not sending the request every time the key up happens now if we compare this to before if I remove the delay here what's going to happen if we go back here and refresh the page if I clear out the developer tools here every time we search it's going to send that request so the benefit of adding the delay is that it's going to wait a little bit of time until the user has stopped typing and only then is it going to send the request to the Django server and that's going to have the benefit of preventing the server becoming overwhelmed by requests using the HX get attribute along with the trigger and that's going to improve performance because your server can then respond to other requests it's going to free up resources and at the end of the day you don't need to respond to every single key up only when the user has stopped typing should you perform that database lookup and return the results to the user and you can amend this interval here for example if you wanted to wait 1 second you can set that to 1,000 m seconds or indeed you can use 1 second so we now have this nice Dynamic search functionality here that's entirely using HTM X in order to send requests to the back end and return this table of responses based on the filtered contacts in the next video we're going to use the HX indicator attribute and we're going to demonstrate how we can respond to user events that are in Flight using things like Spinners to give the user feedback when particular actions are in progress so that's coming up in the next video thank you for watching and we'll see you then
Original Description
In this Django with HTMX series, you'll learn how to make a contacts app using Django for the backend & HTMX for the frontend. You'll also learn how to upload files to Amazon S3 & deploy the app to Render.
🔥🥷🏼Get instant access to ALL premium courses on NetNinja.dev:
https://netninja.dev/
🔥🥷🏼Get instant access to This Course on NetNinja.dev:
https://netninja.dev/p/django-htmx
📂🥷🏼 Access the course files on GitHub:
https://github.com/bugbytes-io/htmx-contacthub
🧠🥷🏼HTMX for Beginners:
https://netninja.dev/p/htmx-for-beginners
🔗👇 Install HTMX:
https://htmx.org/docs/#installing
🔗👇 Install Daisy UI & Tailwind CSS:
https://daisyui.com/docs/install/
🔗👇 Django Storages:
https://django-storages.readthedocs.io/en/latest/
🔗👇 Render:
https://render.com/
🔗👇 Amazon S3 Storage:
https://aws.amazon.com/s3/
Watch on YouTube ↗
(saves to browser)
Sign in to unlock AI tutor explanation · ⚡30
Playlist
Uploads from Net Ninja · Net Ninja · 0 of 60
← Previous
Next →
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Regular Expressions (RegEx) Tutorial #14 - Matching a Username
Net Ninja
Regular Expressions (RegEx) Tutorial #15 - Email RegEx Pattern
Net Ninja
Regular Expressions (RegEx) Tutorial #16 - Finishing Touches
Net Ninja
GraphQL Tutorial #1 - Introduction to GraphQL
Net Ninja
GraphQL Tutorial #2 - A Birdseye View of GraphQL
Net Ninja
GraphQL Tutorial #3 - Project (stack) Overview
Net Ninja
GraphQL Tutorial #4 - Making Queries (front-end preview)
Net Ninja
GraphQL Tutorial #5 - Express App Setup
Net Ninja
GraphQL Tutorial #6 - Setting up GraphQL
Net Ninja
GraphQL Tutorial #7 - GraphQL Schema
Net Ninja
GraphQL Tutorial #8 - Root Query
Net Ninja
GraphQL Tutorial #9 - The Resolve Function
Net Ninja
GraphQL Tutorial #10 - Testing Queries in Graphiql
Net Ninja
GraphQL Tutorial #11 - GraphQL ID Type
Net Ninja
GraphQL Tutorial #12 - Author Type
Net Ninja
GraphQL Tutorial #13 - Type Relations
Net Ninja
GraphQL Tutorial #14 - GraphQL Lists
Net Ninja
GraphQL Tutorial #15 - More on Root Queries
Net Ninja
GraphQL Tutorial #16 - Connecting to mLab
Net Ninja
GraphQL Tutorial #17 - Mongoose Models
Net Ninja
GraphQL Tutorial #18 - Mutations
Net Ninja
GraphQL Tutorial #19 - More on Mutations
Net Ninja
GraphQL Tutorial #20 - Updating the Resolve Functions
Net Ninja
GraphQL Tutorial #21 - GraphQL NonNull
Net Ninja
GraphQL Tutorial #22 - Adding a Front-end
Net Ninja
GraphQL Tutorial #23 - Create React App
Net Ninja
GraphQL Tutorial #24 - Book List Component
Net Ninja
GraphQL Tutorial #25 - Apollo Client Setup
Net Ninja
GraphQL Tutorial #26 - Making Queries from React
Net Ninja
GraphQL Tutorial #27 - Rendering Data in a Component
Net Ninja
GraphQL Tutorial #28 - Add Book Component
Net Ninja
GraphQL Tutorial #29 - External Query File
Net Ninja
GraphQL Tutorial #30 - Updating Component State
Net Ninja
GraphQL Tutorial #31 - Composing Queries
Net Ninja
GraphQL Tutorial #32 - query variables
Net Ninja
GraphQL Tutorial #33 - Re-fetching Queries
Net Ninja
GraphQL Tutorial #34 - Book Details Component
Net Ninja
GraphQL Tutorial #36 - Styling the App
Net Ninja
GraphQL Tutorial #35 - Making a Single Query
Net Ninja
Build Apps with Vue & Firebase - Udemy Course
Net Ninja
Updated Vue & Firebase Course (Udemy)
Net Ninja
Vue & Firebase Real-time Chat (Preview) #1 - Intro
Net Ninja
Vue & Firebase Real-time Chat (Preview) #2 - Project Structure
Net Ninja
Vue & Firebase Real-time Chat (Preview) #3 - Firestore Setup
Net Ninja
Vue & Firebase Real-time Chat (Preview) #4 - Welcome Screen
Net Ninja
Vue & Firebase Real-time Chat (Preview) #5 - Props in Routes
Net Ninja
Vue & Firebase Real-time Chat (Preview) #6 - Route Guards
Net Ninja
Vue & Firebase Real-time Chat (Preview) #7 - Chat Window
Net Ninja
Vue & Firebase Real-time Chat (Preview) #8 - New Message Component
Net Ninja
Object Oriented JavaScript Tutorial #1 - Introduction
Net Ninja
Object Oriented JavaScript Tutorial #2 - Object Literals
Net Ninja
Object Oriented JavaScript Tutorial #3 - Updating Properties
Net Ninja
Object Oriented JavaScript Tutorial #4 - Classes
Net Ninja
Object Oriented JavaScript Tutorial #5 - Class Constructors
Net Ninja
Object Oriented JavaScript Tutorial #6 - Class Methods
Net Ninja
Object Oriented JavaScript Tutorial #7 - Method Chaining
Net Ninja
Object Oriented JavaScript Tutorial #8 - Class Inheritance
Net Ninja
Object Oriented JavaScript Tutorial #9 - Constructors (under the hood)
Net Ninja
Object Oriented JavaScript Tutorial #10 - Prototype
Net Ninja
Object Oriented JavaScript Tutorial #11 - Prototype Inheritance
Net Ninja
Related Reads
📰
📰
📰
📰
Inside the Wayfair Frontend SDE-2 Interview: A Complete Breakdown
Medium · Programming
I Spent Two Years Maintaining a React SPA. HTMX Rebuilt It in a Week
Medium · Programming
The 5 Levels of Front End Engineering (And Where Most Developers Get Stuck)
Medium · Programming
Browser-Based PDF Editing with Vue 3 and pdf-lib
Dev.to · sunshey
🎓
Tutor Explanation
DeepCamp AI