مرور استایلدهی Facet0:00
Alright, so have a look at this. We currently have search results along with clickable filters in the sidebar. And yet each of these filters itself is nothing more than an anchor tag. It fills up the query string, you click on it, it reloads the page and it updates the results. And this is fine, but it's not the most flexible thing in the world. I would love the option to select one.
Switch to checkboxes0:15
but it's not the most flexible thing in the world. I would love the option to select one or many authors that I wanna filter by. So let's figure out how to do that in this video. Let's return to our search page. And now, rather than an anchor tag, I don't think that's gonna work anymore. Instead, why don't we use, uh, traditional form inputs? So let's do this. Why don't we have a label that wraps a checkbox, something like this
So let's do this. Why don't we have a label that wraps a checkbox, something like this and just temporarily, I'm gonna hard code it. Uh, 'cause it's easier to understand. All right, let's have a look in the browser. Now we see it twice because we are hard coding Stephen King within a loop that has two items, but that's okay. We'll fix that in a minute. So why don't we set up the alignment here. Uh, maybe on the label I'll set a class of flex item sensor.
set up the alignment here. Uh, maybe on the label I'll set a class of flex item sensor and then just put a little gap in between the checkbox and the label itself. And that looks good. Now I can select it, but I can't click on the name itself because they're not synced up. So yeah, we could do something like add an ID to the input, maybe author. And then again, this would all be,
to the input, maybe author. And then again, this would all be, uh, determined dynamically. And then I could reference it here. Okay, so now I can select the label or the name itself and that will toggle the checkbox, which is what I want in this case. Okay, now, well if I select this, it should automatically submit the form, right? So sounds like we need
Wrap filters in form1:37
it should automatically submit the form, right? So sounds like we need to wrap this whole thing within a form. Why don't we do that right up here? So here's our form and it's gonna wrap the entire loop as you see there. And I'll reformat next. We no longer need this old code from the previous episode, so I will delete that. And where's our form going?
episode, so I will delete that. And where's our form going? Well, once again, it's gonna go to the search page and it's going to make a GET request as part of that. So you know, right now, because we don't have a name value for the input, uh, it's just gonna submit and not include any of the relevant data we care about. So once again, let's add a name to this. Now here's what we could do.
So once again, let's add a name to this. Now here's what we could do. If you think about it, I want the User to be able to select multiple check boxes. So why don't we have all of the check boxes share the same name and we can use that sort of array like syntax with forms something like this filters[] authors. So that way we could have potentially, um, one or more that gets submitted to the server.
So that way we could have potentially, um, one or more that gets submitted to the server. Okay, cool. So now finally we just need to say, well, when you check on this, uh, when you check this checkbox, I immediately want to submit the form. And I'm just gonna do this in line. If you don't mind, why don't we say onChange this form, submit. And that will be fine. Let's reset our search results. So have a look at the current URL. No query at all.
And that will be fine. Let's reset our search results. So have a look at the current URL. No query at all. Let's look for Harry. And we're still hard coding the author name just for a little bit longer. But notice if I select one of these. Well, we lost our selection, so we'll fix that in just a moment. But if I take a look at the URL, we have our search and we did include filters.
But if I take a look at the URL, we have our search and we did include filters. So filters, authors equals on, but that's not quite what we want, right? We actually want the value to be equal to the author name. So let's set the value equal to the author name like this. Okay, so now one more time. If I select this and I take a look, yeah, we're getting pretty close now. We are sending through Stephen King.
Make filters dynamic3:37
and I take a look, yeah, we're getting pretty close now. We are sending through StephenKing. Okay, now let's make it dynamic. So to give you a little refresher, let's die. Actually let's do dd here on a single filter. And you'll see that we get, uh, for each filter, the count, which is the number of, um, results that this author is responsible for. And then we have the highlighted as well as just the value itself.
And then we have the highlighted as well as just the value itself. So really the only thing I care about here is the value itself. Cool. So let's update this to the filterValue. All right, next, let's do the id and I'd like to do this very quickly. Uh, we wanna be careful about just doing filterValue because that would ultimately end up with something like StephenKing.capitalize
because that would ultimately end up with something like Stephen King capitalize with the space in it. And if he has some kind of hyphen or uh, an apostrophe or something like that, that might mess things up. So very quickly, let's just fix this as a temporary, uh, variable. We'll say something like $id equals filterValue and I'll show you this incrementally. Okay, so let's say ID
and I'll show you this incrementally. Okay, so let's say dd and dump the $id that gives us James Patterson in this case. All right, now let's say str_replace and we're gonna look for any space and replace it with a dash. All right, now we have James-dash-Patterson. Next, let's do strtolower, come back refresh. Now we have lowercase.
Next, let's do strtolower, come back refresh. Now we have lowercase and yeah, I, I'm sure there's uh, other things we should search for. Maybe an apostrophe or something like that. If you wanted to do, uh, a second level. So what I can actually do, you may not know this actually, is to str_replace, you can provide an array. So you do it like this. You could say look for a space
So you do it like this. You could say look for a space and replace it with a dash for the second item in the array, search for an apostrophe and replace that with nothing. So that would be a way to do multi search and replace, come back refresh. We're still gonna get the same thing. But imagine that filterValue was like James. Um, I dunno, for some reason he has an apostrophe there. Patterson, after we make this change.
Um, I dunno, for some reason he has an apostrophe there. Patterson, after we make this change and come back, you'll see that is removed. Whereas before that would not be removed and we'd mess up our value there. All right, just a little tip, something to be aware of there. Okay, so now I could update this to author_id and then if I come down here, this would be author_id, same thing.
id and then if I come down here, this would be author_id, same thing. Okay, finally we can update the filter value and that looks good. Come back, give it a refresh. And now let's look for Shining. Take a look at the URI. Next I'll click on Stephen King. And again, we need to deal with this, but it still updates the filters. So we have filters, authors equal Stephen King.
Preserve query in form6:38
but it still updates the filters. So we have filters, authors equal Stephen King. So now if you think about it, we have two forms. We have a form right here and then we have another form in the sidebar. And that's why when I selected here, we submit that sidebar form. That does not currently include the query string. So again, if you're working with a lot of JavaScript, you'd handle this in different ways.
So again, if you're working with a lot of JavaScript, you'd handle this in different ways. But for now I think what we can do is just set up a hidden inputs, uh, as part of this side form. So we can do something right up here. Let's do input type="hidden". And I'm gonna set the value equal to the query string, or I'm sorry, the query itself. And then we'll say name="q".
or I'm sorry, the query itself. And then we'll say name query. So I'm just ensuring that even when this form gets submitted, we don't forget to include the user search query as part of that. So now if I were to come back, we look for shining here. Is our query string good? I add Stephen King to that. Again, we need to deal with the check status. But if I check the URI, we've retained that the query is shining
But if I check the URI, we've retained that the query is shining and now we've included the filters itself. So now check this out. Let's go back to our routes file. And once again, I'm gonna die if I can type die and dump the request data. Alright, so now yes we get the query and the filters, but one little thing, notice that authors is actually set to a string. So filters is properly an array, remember?
that authors is actually set to a string. So filters is properly an array, remember? And that's our facets. We could have any number of those, but authors could also be one or many authors that we wanna filter by. But right now it's set to a string. Alright? So let's just turn that into an array effectively as well. Let's return to our search and here is the name. So we have filters, authors, but let's just add one more. So now take a look at this.
So we have filters, authors, but let's just add one more. So now take a look at this. Let's resubmit the form, Stephen King. And once again, if I die and dump what we have there now, filters, authors is itself an array. So now we have support for filtering by any number of authors. Okay? So now at this point, if I were to die and dump request->filters->authors, if I come back
Build multi-author filter8:40
Okay? So now at this point, if I were to die and dump request filters, authors, if I come back and refresh, now this will be an array. Okay? So let's think about it now. Hmm. We have filters, authors, which is an array of author names. Here's what we might do. Let's come down here and say, okay, well if we have any authors, then when we construct our filter syntax, well I can't just do this, right?
then when we construct our filter syntax, well I can't just do this, right? So if I were to die and dump the $searchParams, yeah, actually we can't even get that far because we're trying to convert an array into a string. Okay? So let's do this, let's say implode. And we're gonna separate them by a space. Okay? So now if we die and dump the $searchParams, there we go. We're starting to get there. But now think about it. What if we had multiple authors like this?
We're starting to get there. But now think about it. What if we had multiple authors like this? It's a little hard to read, but yeah, if we did another one and filters authors equals um, John Doe or something like that, well now notice we're saying, all right, filter this down where the authors equals Stephen King comma John Doe. That's not what we want at this point. We have to decide, do we wanna say where Stephen King and John Doe are both the authors of a book?
We have to decide, do we wanna say where Stephen King and John Doe are both the authors of a book? And that would only be the case if like they wrote a book together. Or do we wanna say no, gimme any books where the author is either Stephen King or John Doe. So one, so potentially one or the other, right? So if we wanna do that, we need a different syntax here. Why don't we use the array syntax like this authors and our operators gonna be an array in this case, right?
Why don't we use the array syntax like this authors and our operators gonna be an array in this case, right? So we learned that we have A, B, C and we're saying, well it has to be one of these items. That's how we do that. So come back, give it refresh. And there we go. So yeah, whenever you see this erase syntax, just think is one of authors is one of Stephen King or John Doe. Cool. So, um, we might wanna do a little tweaking there, but it's enough to get us started, alright?
Keep checkboxes checked10:49
Cool. So, um, we might wanna do a little tweaking there, but it's enough to get us started, alright? And it seems to be working very cool. So now notice that even though I have selected Stephen King and it is in fact represented within the your eye, it's not currently checked. So we can do that very quickly. Let's go into our search view. And yes, as you know, you can just set checked here and that would turn it on.
And yes, as you know, you can just set checked here and that would turn it on, but it'll turn all of them on of course, which we don't want. So you may not know this, but Laravel has a handy dandy checked Blade directive. So if you give it a boolean, it will be listed as uh, checked. If you give it false, of course it'll be deselected. So let's just dynamically figure out whether
If you give it false, of course it'll be deselected. So let's just dynamically figure out whether or not this, uh, checkbox should be checked. Maybe something like this. So if you think about it, if we were to look within request filters.authors, that's going to include an array of all the authors who have currently been selected, right? So all of the authors who should have checked check boxes, right? So why don't we just look in that array?
who should have checked check boxes, right? So why don't we just look in that array and see, well, do we see one that contains the current author name in the loop? And if so, it should be checked. All right, easy enough. Let's say needle, our needle is the current author's name. Our haystack is going to be this array here. And I think with any luck, that should do it. So let's come back and give it a refresh argument.
And I think with any luck, that should do it. So let's come back and give it a refresh argument. Two must be of type array, but null was given. Ah, that would be because uh, in this case, if we haven't selected any, then of course filters, authors will be, um, null. So let's make sure it's always set to, if nothing else, an array come back, give it a refresh. And now let's look for shining good. Let's uh, choose Stephen King.
And now let's look for shining good. Let's uh, choose Stephen King. Now it's selected and I see only the results that have that match, which is cool. Alright, so now let's just do a tiny bit of cleanup. We have a couple more things to make dynamic and then I'm gonna let you go. All right, so you'll notice right now we're still hard coding author even though we're within a loop. So if I were to dye
coding author even though we're within a loop. So if I were to dye and dump, uh, the facet itself, of course we can fetch the author or the facet name dynamically. So let's do that now so I can change this to facet name. And yet you can see why I, I I chose to hardcode things at the beginning just because this can get a little, a little confusing, right? But if you, if you refactor to this, it's not quite
because this can get a little, a little confusing, right? But if you, if you refactor to this, it's not quite as confusing 'cause you already know what it is. Okay? So I'm gonna update this to facetName as well. This can become facetName. And finally this one as well. All right, let's make sure everything is still working. Give it a refresh that looks good. Dark resets, everything I can now select to filter it down. This looks good to me. Next up this section right here, ah,
Move logic to route13:33
Dark resets, everything I can now select to filter it down. This looks good to me. Next up this section right here, ah, it's probably okay, but if you don't like the idea of doing that within your view, that's fine as well. Here's what we can maybe do instead. Let's copy this and return to the routes file. And yeah, here's where we have our facet counts and then we have filters. So once again, let's just dd facets.
and then we have filters. So once again, let's just die and dump facets. Uh, let's fix that facetCount to show you what we have here. Yeah, and now we have an array where each one of these represents a single filter. So why don't we just override that and be explicit about the data that we wanna send to the view. So here's what I'll do right here.
that we wanna send to the view. So here's what I'll do right here. Uh, let's do this collect, let all of these and let's map over them. We're gonna call this filter and yeah, I'm just gonna be clear what I want. I wanna return the account would probably be helpful. So let's grab that filter count next value. That's fine. Um, I kind of like name more though.
count next value. That's fine. Um, I kind of like name more though. This is the filter name rather than just generic value. So why don't we update that and then we'll tweak the view. And then finally we're gonna give it a ID that can be used for IDs or slugs or something like that. So this is where I can paste in that code from before. And let's just clean this up and yeah, that looks good to me. So now if I were to dye and dump the facets
and yeah, that looks good to me. So now if I were to dye and dump the facets and let's run pint, come back, give it a refresh. Alright, so we have our collection. Here is our facet. Here are the filters for each one. That seems right. So now why don't we turn this back into an array. I don't think it matters too much, but I wanna be very clear. So we have filters. Here's our items. That looks good. Okay, so now if you think about it, when we return
So we have filters. Here's our items. That looks good. Okay, so now if you think about it, when we return to our view, I no longer have to do this junk here. I can instead replace ID with filterId. And then finally we decided we didn't like value, did we? So we swapped that out with name just to make it a little more clear. This should be the name of the filter and I think that should do it.
This should be the name of the filter and I think that should do it. Alright, so let's do our final check. And this is looking good to me. Filtering. This is all working. I can turn it on and off. This is looking great and I know maybe this video is a little bit long-winded and I'm sorry about that. But I think it's really important to go step by step so that you understand what each value does and why we're doing it in such a way,
Preview instant search16:07
that you understand what each value does and why we're doing it in such a way, what this little thing means there and why we're doing it in that way. Alright, so in the next section, let's take a break from Faceting and instead focus on instant search. As I type here, I immediately wanna see every 300 milliseconds or so updated search results.
I immediately wanna see every 300 milliseconds or so updated search results. How on earth do we do that? I'll show you how.
