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