HTMX + Flask: Modern Python Web Apps, Hold the JavaScript Transcripts
Chapter: Feature 2: Active search
Lecture: Searching as they type with htmx

Login or purchase this course to watch this video and the rest of the course contents.
0:00 So we've got this basic input field that we ask users to search by typing in
0:05 Of course it does nothing yet because we haven't done our htmx
0:08 magic. Again, to do htmx, we do hx
0:13 and then, what? The first thing we want to do is we want to do GET
0:19 and this is gonna be /videos/search and then we have to have an
0:25 hx-trigger. What is going to cause this to happen and then gonna
0:29 be a key up changed delay 250.
0:33 So let's break this apart key up is basically as they release the keys as they
0:37 type. So if we did just this that would totally work.
0:40 But it would be very spastic. It would be every single keystroke would be going to
0:44 the server and results will be coming back and it would be totally crazy.
0:49 Instead we're going to have changed and a delay.
0:54 The delay means you can type as much as you want, but it will only go
0:58 to the server if you stop for a quarter second between your typing that may be you've
1:03 only typed part of it and you're thinking and you'll see some results come in and
1:06 you'll type some more and the results will update or it could be you typed really
1:10 quick and then boom, the results show up but it won't every single keystroke start
1:15 hammering the server and giving some weird experience.
1:18 The other one is not every keystroke actually results in different data being sent to the
1:24 server. So if I press the letter A and then letter B those keystrokes
1:29 should have some kind of effect.
1:30 Right? I could have searched for absolute or whatever.
1:34 However if I use the right arrow and the left arrow key that's not changing
1:38 the content of that text box.
1:40 We don't want to rerun the same search over and over just because you're mousing around
1:45 or arrowing around inside there. So change means there has to both be a keyup
1:50 and the result has to have changed the contents of the text box and it
1:54 has to wait for 250 milliseconds then rerun the search.
1:59 And then the last thing is hx-target and here we put the CSS selector of
2:06 where the results go which is search/results that will do it.
2:11 I think. It's going to do something really weird.
2:13 It's not gonna come out well, but it's gonna, I think it's going to do it.
2:18 Let's give it a try, refresh it here and now let me type something like apple.
2:24 That's weird, lool at that I could type inside myself it's like inception for search
2:31 and so on. We could put indycar or whatever and now we're getting
2:36 the results and hear what in the world is this?
2:39 Well remember we're going to this URL
2:41 For the page,
2:44 the entire page right let's get rid of the search thing.
2:46 It's not really participating. We go here and then we said our target, our
2:52 GET is /video/search.
2:57 That's the same thing. How is this ever gonna work?
3:00 Right. So if I put apple here,
3:02 it's gonna say great, I went there,
3:03 the page that came back is the entire website and it jammed it in there.
3:08 So what we need to do is we need to differentiate between somebody coming like this
3:14 and somebody coming there by through htmx.
3:17 Now you might say, we'll just make two views that are basically the same,
3:22 but one returns a partial and one doesn't,
3:24 we can do that and that's fine,
3:26 but we're also going to need to deal with this search_text=apple deep linking
3:31 things. So we want to kind of process it in both places anyway,
3:35 so really what happens is it's identical code.
3:38 The only different choice is what is being sent back.
3:42 We're going to need to change that over on the server, here.
3:47 Now, when this request comes in directly from the browser,
3:51 it's just a standard old request,
3:54 but when it comes in differently when it comes in from htmx, htmx
3:59 says you might need to treat this separately,
4:02 you might need to treat it differently. To enable us to do that,
4:05 they actually put a header in the request, so they put a header over and we
4:09 can check is this an htmx request?
4:12 So we'll say something like if vm.is_htmx_request,
4:19 which we don't have, then return something else.
4:23 Let's return something real simple. Like we'll just say how many videos there are for
4:27 the moment. That's not really helping them because we got to actually render them,
4:31 but well we got to create some more HTML to make that happen. Now,
4:34 what about this? Let's go over here, and you might say,
4:37 well let's put it into the search model, but we have this cool base class and
4:41 it's very likely other parts of our site in the future will also possibly need to
4:45 make the same decision. So let's go down into here.
4:49 Well say something like this self.is_htmx_request.
4:54 And then what we need to do is ask if there's a certain string in
4:58 flask.request.headers. We don't care what its value is.
5:02 Just, is this header present? and that header text or the header keyword key is
5:08 HX-Request capitalized like this.
5:12 So if htmx makes a request,
5:15 it's going to also add this header to say,
5:17 hey, this is just coming from us in case you need to do something different
5:20 than normal. So we're going to try to use that here. When a request comes
5:26 in like this, we're going to give them a different set of HTML.
5:29 In this case, incredibly simple HTML rather than rendering the entire page back.
5:34 Let's try again. So we refresh this page come over here and let's just type
5:41 apple. Oh, something has gone wrong,
5:46 ah we expected a dictionary, that's right because the way that this is set up
5:51 we need to return something like this flask.make_response, there we go.
6:02 So we had to call flask.make_response.
6:04 But you know,
6:06 there are four videos. How about racing?
6:08 How many videos are there on that?
6:11 How about indycar? two videos on indycar, Python?
6:15 six videos on Python. Now we're not rendering the results, but we're doing the search
6:21 and we're sending it back actively.
6:24 It does that delay and it does change, freeze the arrow keys.
6:26 Although I guess we can't really tell you would see the at least back here,
6:29 you would see there are no more changes.
6:31 So you see those are not moving by but check it out down here,
6:35 you can actually see the request coming in as a query string.
6:39 You see py, py, python, all the stuff that's coming in indy,
6:45 indycar, racing, racing, that's how it's communicating back to the server.
6:49 So it's exactly matching what we already set up here, and it's sending the header over
6:56 so we know to treat it differently and just send that little bit back and not
6:59 do that crazy inception thing.
7:02 This is pretty awesome. We're super, super close, we just need a little more HTML to make this look real.