- Read Tutorial
- Watch Guide Video
One of the very first things that you may have noticed is if you come here to the home page and you search for something, so I searched for Vue
right here. A typical kind of user experience is that it would pre-fill this form element with the search query.
Right now, it's just starting with a blank slate. It may be giving us our results but usually, it's kind of nice to have this pre-filled in. Let's start with that. The way we're going to do it is we are going to come up to the input tag
, and make sure you're in SearchResults.vue component here.
I'm going to add another directive here. This is going to be:
SearchResults.vue
<div class="search-bar results-search-bar"> <input type="text" :value="query" :placeholder="searchPlaceholder" @keyup.enter="submitQuery"> </div>
Inside of here, I'm simply going to call whatever the query was. I'm going to say :value="query"
. Now if I come here and search, you can see that now it's prefilled in with that query. I think that is working well.
Now let's see what happens if we look for something here. You can see that it's still working. I'm happy with that implementation.
I think the value inside of the query, or inside of the form element now is working. That part of it is done, and I think that leads to a better user experience. Now the next thing that I want to do is I want to add some validations.
Watch what happens here. If I clear this out and I press enter. It just gets empty space which isn't exactly the ideal scenario. You're going to see in a second that when we add our little loading
element.
In fact, let's do that first because that's going to show even why we need this even more. What I'm going to do is I want instead of just having the page be blank, and even though it may seem like it's really fast, I think it makes sense to have some little piece of text that says "hey, we're going out and we're getting your results."
This also should help you understand state
a little bit as well. What I want to do is inside of the results-post-wrapper
, I want to add a div
. We'll add a couple of them. Right now, let's just add 1, and inside of here I'm going to put in an H2
that says loading
.
SearchResults.vue
<div class="results-posts-wrapper"> <div> <h2>Loading...</h2> </div>
What I need to do is I need to check to see if we are getting results or not. There are a few ways of doing that and I'm going to add a v-if
directive here. It's going to say gettingResults
. Obviously, this is something we don't have yet.
SearchResults.vue
<div class="results-posts-wrapper"> <div v-if="gettingResults"> <h2>Loading...</h2> </div>
Let's come down into our data element here, and let's add a new one called gettingResults
. By default, we are going to set it to true
.
SearchResults.vue
export default { name: "SearchResults", data() { return { query: null, results: [], searchPlaceholder: `\uf002 Search DailySmarty`, gettingResults: true };
Remember this data element here is created as soon as a component is loaded, so getting results is the default behavior. Any time that the search result page is about to load, we are getting results.
Now that we have that, what we can do is we are going to hit save and just make sure that we don't have any typo's or anything. You can see it shows Loading...
. Obviously, we want to remove this as soon as the results show up.
That is something that you may guess we already have a spot for that. We don't want to put this in beforeMount
yet. We don't put it there because that's not really getting us what we're looking for.
Instead, if we come down into the then
block right here, where we have our response. This is where we know if the results came in or not. Right underneath where it says this.results.push
, we can here say:
SearchResults.vue
axios .get("https://api.dailysmarty.com/search", { params: { q } }) .then(response => { this.results.push(...response.data.posts); this.gettingResults = false; console.log(response.data.posts);
Because we are no longer getting the results after they've been added to the results array. Now you can see that that is gone, and if you come right here, and type something, you can see it. It's very brief because this works very fast, but it did show loading there for a second.
That is working nicely. Now with that in place now I can show you the little data validation problem we have. If I clear the search query out, and I press enter then we still don't have anything showing up. It doesn't say loading, and nothing really happens,
That's kind of the expected behavior. We don't really want anything there, but it still should add some kind of data validation. It should say something like "hey, you really need to type something in," or something like that. So let's add another element.
If I come up here to where I have the v-if
, and right underneath it, I'm going to add another div. Inside of here, this is where I'll add another H2
and say You need to enter a query
. I'm going to use another v-if
directive here. I'm going to say v-if="!query"
.
SearchResults.vue
<div class="results-posts-wrapper"> <div v-if="gettingResults"> <h2>Loading...</h2> </div> <div v-if="!query"> <h2>You need to enter a query</h2> </div>
All this means, if you ever see this syntax in JavaScript, this is the same thing as saying v-if="query == null"
or v-if="query == false"
. I just like the syntax of putting a bang
right in front of the query. Actually look let's move this right above here and hit save.
SearchResults.vue
<div class="results-posts-wrapper"> <div v-if="!query"> <h2>You need to enter a query</h2> </div> <div v-if="gettingResults"> <h2>Loading...</h2> </div>
Now if we come up, and if I clear this query out and hit search, you can see we have our data validation there in place. That is working nicely. It says You need to enter a query
.
All of that is looking good. I really think I only have one more feature that I want to build in. I think we have time now to do that and that is what happens when we type a query that doesn't exist. If I look for something like this, you can see that nothing happens, but that's really confusing.
I would much rather have something that says there are no results for your query. Let's come down here, and in this case I'm going to move a v-if
. We can copy this one. I'm going to move this all the way down below.
Now what I'm going to do is I'm going to add to in a check. This is going to say v-if
. This is something a little tricky. If we're getting the results, I do not want to show this. It would be a really bad user experience if we showed loading or if we showed this while it was loading.
I want to make sure that this does not trigger if we're currently getting results. So we're going to make sure that gettingResults
is false
or null
. After that we're going to also check for the results length.
So I'm going to say results.length
and if it is equal to 0
. Then inside of here, I'm going to say There are no results for your query
. Hit save, and let's see if that did the trick.
SearchResults.vue
<div v-if="!gettingResults && results.length == 0"> <h2>There are no results for your query</h2> </div>
I guess there was one for that query. This is one of the issues when you're working with this kind of data. If there is any kind of weird search elements inside of the API. There you go.
If you run that query with that other data, apparently, that's somewhere on the page. So that was brought in. This data or this search where he didn't find any records and this is the result we want where it says There are no results for your query
.
We'll fix that spelling mistake here, and we're good to go. This is working perfectly. I don't really see anything else that needs to change in the application. We'll just review everything.
We have our design implementation. We're connecting out to an outside API service. We're able to run a full set of queries on the search results page. We have data validations in place.
We have some user experience tools such as showing when elements are loading, or when a user is not typing in something, or they are typing something that they really shouldn't in order to get the behavior they're looking for.
I think it turned out really good. Great job if you went through that. You now know how to build out a full API based application using VueJS.