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.