در حال بارگذاری ...

Introducing Live Search0:03

All right, so let's do this. I wanna take things up a notch and show you how to implement live search or instant search. And I'd also like to show you how we can, for example, bind to an input so that we can track the user's query and we can also track which filters they've applied. And definitely you can do this all with vanilla JavaScript of course, but you're probably not, you're probably using a dedicated tool in real life, like React or Vue.

Installing Vue and Inertia0:23

you're probably using a dedicated tool in real life, like React or Vue. So with that in mind, I'm gonna set up a Vue and Inertia project that should be pretty familiar to many of you, but keep in mind it does take five or six minutes. So we have two choices here. Choice number one, if you choose to accept it, is come along for the five minutes and just watch me install and configure Vue and Inertia and Vite on the other hand, if you've done

and configure Vue and Inertia and Vue on the other hand, if you've done that a million times and you just don't care, click on this timestamp right here and we will immediately jump to the type sense part. All right, make your choice, let's get going. All right, so the first thing I'm gonna do is install Vue and then next we should pull in of course InertiaJs. So if you're not familiar with this, it's like the glue between Laravel app and your front end SPA.

So if you're not familiar with this, it's like the glue between Laravel app and your front end SPA. So we're gonna do the server side installation and we will require this through composer. I'll paste that in and then next we'll set up the root template shortly. But before we get there, let's come into the client side installation. And if I scroll down, we uh, we will pull in the Vue 3 Inertia library.

And if I scroll down, we uh, we will pull in the view inertia library. All right, next step of course we're gonna use view and Inertia with VT as our bundler. So we're gonna make sure we pull in the VJs plugin view package. And again, you'll find all of this in the documentation. All right, so let's open this in my editor and start configuring. Alright, so let's open up our project's VT configuration.

and start configuring. Alright, so let's open up our project's vt configuration file and we will pull in the view plugin, I'll just call it view and then I will register it as a vt plugin. But now we might want some configuration. So let's switch over to the Laravel documentation and this is the section for asset bundling. And let's scroll down to the instructions for view. And yeah, they have some general guidelines

And let's scroll down to the instructions for review. And yeah, they have some general guidelines we might wanna pull from. So why don't we paste that in here. Alright, so setting this to null allows the layer of L plugin to instead rewrite asset URLs to point to the V server instead. Yeah, you don't even need to worry about this too much, just copy and be done with it. Okay, next up we're almost there.

just copy and be done with it. Okay, next up we're almost there. We're gonna set up uh, the Inertia layer. So here's how, let's return back to Inertia's website. We're gonna go into our server side installation and we're gonna set up our route template. So here's what I can do. I can open up app.php, which doesn't exist yet. So let's do that. Now this is basically our entry point. There we go. Notice we are referencing the Inertia directive.

So let's do that. Now this is basically our entry point. There we go. Notice we are referencing the inertia directive and we also have the head section and we're referencing our V file that is being compiled, or I'm sorry, our v bundler that's going to compile app.js. All right, next if I scroll down, we need to set up the inertia middleware. So let's run that now. Very good. And then finally we will register it within our bootstrap/app.php file.

And then finally we will register it within our bootstrap/app.php file. So again, if you've ever done something like this in a Laravel app, this is all basically uh, a refresher middleware set up a web and this is handle Inertia requests. All right, let's switch back. Now we can return an Inertia response like so Inertia::render. All right, now let's move over to the client side setup. And this is where we will initialize our app so

Initializing Inertia App3:47

All right, now let's move over to the client side setup. And this is where we will initialize our app so we can copy this and go into our JavaScript app entry point. And I'm just gonna paste all of this and I don't think we even need bootstrap, so I will delete that entirely. Alright, so now this is our app entry point. We import, uh, createApp from vue and then createInertiaApp from inertia of course, and we instantiate it.

and then create inertia app from um, inertia of course, and we instantiate it. Let's have a look. This is how we resolve which page component you want. So it's gonna scan all of your pages and we'll do this now pages, um, any page components within there and it'll match it up with the one you select or the one you return from the controller. And then finally, this is where we set up our view app,

or the one you return from the controller. And then finally, this is where we set up our view app, create the app, use the uh, the given plugin and mount it to our root uh, container. So this is looking good. If I go back to vconfig, you can see we are referencing resources/js/app.js. So now I can boot up my vet server like this npm run dev and that's up and running. Okay, so now let's see if we can get this to work.

Creating Search Page4:54

NPM run dev and that's up and running. Okay, so now let's see if we can get this to work. Here's what we'll do. Let's go back to our routes file. And of course we have our search playground, but just for now, I'm just gonna comment it all out. And at the very top, I'm gonna replace this by returning an Inertia page component. So I can say Inertia::render. And why don't we call this search/index? All right, so let's open up pages,

And why don't we call this search index? All right, so let's open up pages, create a new directory called search and within it a view component called index. All right, right here we'll say hello world. All right, so are we all on the same page? We have set up our Ve server, we've configured Inertia, we've pulled in all of the dependencies, and then in our routes file when we visit the search page, we will try to return this search index view component.

and then in our routes file when we visit the search page, we will try to return this search index view component that should render Hello world to the page. Let's see if we got it to work. Let's go to supercharge/search. And there we go, we're up and running. Alright, so now I'm gonna switch back. I'm gonna snap my fingers and all of you who skipped the view installation step will be all caught up.

and all of you who skipped the View installation step will be all caught up. 1, 2, 3. Welcome back. I now have a fully installed View and Inertia, SPA, you can see we have our first search page component and we are rendering it to the page. Now let's get to work. Alright, so let's do this. I'm gonna show you how to provide instant feedback to the user as they type.

Binding Query and Results6:23

I'm gonna show you how to provide instant feedback to the user as they type. But often you'll wanna pull in a package and you can still do that and I'll show you how to do that in the next episode. But for now, let's just bind to an input. Listen for when the user types and then perform an HX call. Alright, here's how first I will set up my inputs. We'll give it a type of search and we will bind to it so I can track what the value is.

We'll give it a type of search and we will bind to it so I can track what the value is and I'll simply call it search. Or actually better yet, why don't we call it query? All right, so let's do this. At the very top I will define our query and this will be a ref that we track. Next, this component is going to accept some results, uh, of sorts. So I'll say results should be an array

to accept some results, uh, of sorts. So I'll say results should be an array and then I will simply loop over the results and display the title of the, the item or the document, uh, below it. And we'll do that right here. Yeah, let's let AI help us out, something like this. If we have any results, then within a list we will loop over the results and we will provide um, the name or maybe it's title

then within a list we will loop over the results and we will provide um, the name or maybe it's title and yeah, generally it's a good practice to uh, include a key. We're just gonna skip over it 'cause we don't care. In this case this is fine and simple. So let's finish this up and have a look in the browser. Okay, so if we view this in my browser, we get uh, the dreaded white screen of death that we all hate, but hopefully it's not a big issue.

the dreaded white screen of death that we all hate, but hopefully it's not a big issue. We'll go to the console and yet we can see trying to read a property length on undefined. And here's the issue. We read results at length, but we never passed in results as an array. So let's do this. Let's say yes, it's an array, the default is going to be an array. That way we avoid that issue even if we do not provide any results.

That way we avoid that issue even if we do not provide any results. So now if I come back and give it a refresh, sure enough, we see our search bar. Okay, very cool. Alright, so let's do this. I'm gonna open up my dev tools again, I have the Vue Chrome extension installed and if I come down to index, sure enough we have our results prop, which is an empty array currently,

sure enough we have our results prop, which is an empty array currently, and we have our query which is blank, but if I type into it because we are using v-bind with it, we can now track that query. So as you can imagine, all we want to do is listen for when the user types into this and as they do at a certain interval, make an Ajax request to fetch the latest uh, search results from TypeSense. And that's what we're gonna do. Alright, so quick and dirty.

to fetch the latest uh, search results from typesense. And that's what we're gonna do. Alright, so quick and dirty. The first thing we'll do is this. We'll say watch our query and yeah, when it changes, we will run this function. So if I were to simply say console.log the query, well if this is working as we type, we should log something to the console. So give it a refresh and I will say H-E-L-L-O. And sure enough, incrementally we are calling

So give it a refresh and I will say H-E-L-L-O. And sure enough, incrementally we are calling that function, which is great. Cool. So if you want, we can accept the new query here or the updated query. And yeah, all we're gonna do is use Inertia's router component and notice I imported it here to effectively reload the page. And here's how. So let's do router.reload. So I'm gonna do reload instead of get

And here's how. So let's do router reload. So I'm gonna do reload instead of get or visit, uh, it's just a shorthand. Basically, it visits the current page, but it also preserves any states that you currently have. Otherwise, unless you explicitly enable it, uh, of course the search query input would clear out when the page reloads. This will prevent that from happening. Alright, so now I'm gonna send

This will prevent that from happening. Alright, so now I'm gonna send through the query and we'll do it like this. $q equals new Query. All right, so it's not very performant, but hopefully this should work. Let's have a look in the browser. So I will open up the network tab and we have XHR and yeah, I will search for something JEF. So notice right now it's every single

and yeah, I will search for something JEF. So notice right now it's every single keystroke, which isn't ideal. We should debounce this, uh, ideally, but just to show you it's working, we are making this request to the search page and we are passing through the query. This is what we want. Okay, so now let's update the backend and then we, and then we will return to this and clean things up a little bit.

Wiring Backend Search Results10:32

and then we, and then we will return to this and clean things up a little bit. I will go to my routes file and let's uncomment all of this, but we're gonna change things up just a little bit. So let's clean this up and we'll say in this case, we're not gonna be working with facets currently. So I can get rid of this section here. Alright, so this can now go to the bottom like so, and I think this looks pretty good.

Alright, so this can now go to the bottom like so, and I think this looks pretty good. All right, so let's have a look together. When you hit this page, we will look into the query string if you have anything. If you didn't provide anything, we'll just search everything. We set up our search pers we're gonna search through the title of our books. We will reach for our books collection.

through the title of our books. We will reach for our books collection and search through all the documents. We will then fetch the results, like, so, um, we will collect the highlighted portion. Now we need to be a little careful of this because if we aren't searching for anything, there won't be anything highlighted, which means this may not give us what we want, but that's okay.

which means this may not give us what we want, but that's okay. We can return to that shortly. And then finally we re uh, we pass those results to our front end. Now if I click through to our front end, we accept those results. And then right down here, as long as it's not empty, we loop over the results and display the title only. And I think that's right.

we loop over the results and display the title only. And I think that's right. We'll double check to make sure it's called title. Yeah, it looks like it's not very quickly. Let's see what we are passing here for results. Ah, it's just a, oh, that's right, it's just a basic array here. So we can just echo the result itself. And now if I come back, we get our search results and sure enough, because we are using the highlighted uh,

And now if I come back, we get our search results and sure enough, because we are using the highlighted uh, value, once again we get the mark tags. So let's make sure that we use VHTML in this case, come back and then here we go. Dark. It works. And again, notice, uh, I even forget I'm doing this, but as I'm typing, we're getting immediate feedback. If I look for Potter, P-O-T-T-E-R, it's very quick and very responsive.

If I look for Potter, P-O-T-T-E-R, it's very quick and very responsive. However, that being said, maybe it's a little bit too responsive because well imagine this, if I open up the network tab and I just start searching, we're gonna get lots and lots of results and, and very quickly this could be a massive bottleneck. So generally, yeah, when you are binding to an input and you're watching it and performing Ajax calls,

Debouncing Search Requests12:50

So generally, yeah, when you are binding to an input and you're watching it and performing Ajax calls, you wanna do a general deep bounce, which is basically listen for when the user stops typing and then perform the search. So something like this or another option would be to throttle to say, well, at most we're going to make, um, a few calls per second or every two seconds. It just depends on what you wanna do here.

a few calls per second or every two seconds. It just depends on what you wanna do here. Alright, lemme show you how. So let's scroll up and here's our watcher. Uh, of course we could pull in a dedicated, um, function, maybe use lodash and they have a debounce function that we could pull in. But also if you want, it's, it's very simple, you can just implement it like this. You could say let timeout equals null.

you can just implement it like this. You could say let timeout equals null. And yeah, here's what we're gonna do right down here. Think about it. Every time the user presses a key, we will call the function here. So what I'm gonna do is set a timeout and after an arbitrary amount of time, whatever you decide, maybe half a second, if the user stops typing for half a second, at that point only we will quickly make an HX call.

for half a second, at that point only we will quickly make an HX call to provide some results. If you wanna reduce this to 400 is is whatever you want, whatever feels right to you. Alright? So the thing that makes this work is immediately after the user types we will clear the timeout. So I'll say timeout equals this, but at the very beginning I will clear the timeout. Alright, so yeah, just very quickly, I bet you didn't expect

but at the very beginning I will clear the timeout. Alright, so yeah, just very quickly, I bet you didn't expect to ou refresher. So let's say the user types a key. We immediately run this code, we clear a timeout, there isn't one currently and that's okay. But then we make a timeout and we wait 400 milliseconds, but in less than 400 milliseconds, the user types their second key. So now we run this code again

the user types their second key. So now we run this code again and we clear the timeout that we just set before here. So that means the timeout for the first keystroke never completes and we keep doing that over and over until it has been at least 400 milliseconds and at that point this code will run. And yeah, this is just a simple deep balance implementation. I'll show you how Back to Chrome.

And yeah, this is just a simple deep balance implementation. I'll show you how Back to Chrome. Let's open up the network tab once again and I'm just gonna keep typing and I'm not going to allow 400 milliseconds, but when I stop instantly you see results there. And yeah, simple Deb bounce. So think if I were doing something like this, like 1:00 AM I searching for you in real life, you'll have a little bit of pause,

like 1:00 AM I searching for you in real life, you'll have a little bit of pause, but now we are performing just a few queries versus potentially dozens and dozens. So maybe, um, what is that? That book Dark Matter, it's something like dark. What is it? Ah, we get some results matter. You can see how this works. Uh, this is a much more performant way to go about it. Here's the thing to keep in mind. It's so simple, right? So if you had it in your mind that you needed

Here's the thing to keep in mind. It's so simple, right? So if you had it in your mind that you needed to pull in a dedicated tool to provide instant search, well you can and they do have some bells and whistles, but you don't have to. Uh, if you just want some pretty quick feedback to the user as they're typing, then this is the way to go. And of course, style this however you want to make it look nice and clean. You can toggle it, you can slide it down,

however you want to make it look nice and clean. You can toggle it, you can slide it down, you can do whatever fun stuff you want, but the implementation itself is wildly easy. Alright? So with that being said, in the next episode, I am gonna show you one of those dedicated tools. So have a look at instant search in the next episode.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟