Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Adding an [x] to our Search Bar

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

When we type inside the search bar, it actually already has a little X icon on the right. That's because we're using an <input type="search"/> for the search bar. And in my browser, this adds an X icon.

But... can we pretend that doesn't exist for a moment? Because I want to see if we can add our own little X icon that, on click, will clear the search term. This will be a great opportunity to practice our new dangerous skills!

Add the Button!

Inside of search-bar.vue, add a class to the outer div called input-group. That will let us add a new <div> element at the bottom, which will hold the "X" button. Give it class="input-group-append" and a v-show. Let's see: we only want to show the "X" button if the search term is not empty. Do that with v-show="searchTerm" - to reference that data - != "".

<template>
<div class="input-group">
... lines 3 - 11
<div
class="input-group-append"
v-show="searchTerm !== ''"
>
... lines 16 - 20
</div>
</div>
</template>
... lines 24 - 48

Now, inside the div, add a <button> - I'll talk about that ESLint error soon - with an X as the text and class="btn btn-outline-secondary".

Ok ESLint: what's up? Hmm: v-show should go before class. Ah, we've seen this a few times before: attributes can go in any order, but there are some best-practices. Swap these two attributes and... ESLint is happy. I'm happy!

... lines 1 - 11
<div
class="input-group-append"
v-show="searchTerm !== ''"
>
<button
class="btn btn-outline-secondary"
>
X
</button>
</div>
... lines 22 - 48

Over in the browser... there we go! It looks a little silly because of the double X, but remember! We're ignoring that! I want to see if we can get our button working: on click, we want to clear the search bar.

Adding Behavior to the [x]

And... I know how to do this! I'll just ask Siri to do it for me! Or, we can listen to the click event! So we need v-on, but of course we'll use the shortcut. Say: @click="" set to a new method called eraseSearchTerm. Copy that method name and, below - we already have a methods section - so paste this as a second key.

<template>
... lines 2 - 15
<button
class="btn btn-outline-secondary"
@click="eraseSearchTerm"
>
... lines 20 - 23
</template>
... lines 25 - 52

Inside, we just need this.searchTerm = ''.

... lines 1 - 25
<script>
export default {
... lines 28 - 34
methods: {
... lines 36 - 45
eraseSearchTerm() {
this.searchTerm = '';
},
},
};
</script>

We're crushing it!

Back to Testing in the Browser

Time to test! Let's refresh... do a quick search... and click the X button. Boom! The search cleared. Oh, but the products did not update! Siri, could you.. update those for me?

When we think about the search-bar component, the searchTerm data is entirely internal. The only reason we have a searchTerm data at all is just to make our life easier... inside that component. For example, it helps us up here to know whether or not we should hide or show the X button.

But for people that use this component, all they know and care about is that search-bar emits a search-products event. And that is what we're missing in eraseSearchTerm()! We correctly updated the internal data, but we forgot the most important part: emitting the event.

Copy the $emit() statement and use it here. Of course we know searchTerm will always be empty, but this will work fine.

... lines 1 - 34
methods: {
... lines 36 - 45
eraseSearchTerm() {
this.searchTerm = '';
this.$emit('search-products', { term: this.searchTerm });
},
},
... lines 51 - 53

Check that it all Works!

Now when we go over... search for something cool... and clear it... yea! We got it! Making this work was nothing new, but it was a great exercise to think about the internal and external parts of our search-input component.

Next let's do something I'm really excited about! The currentCategoryId is something that we set on page load and then never change. But we've organized our app in such a good way that with a little bit of logic and a new concept called a watcher, we're going to be able to dynamically change the category and have the whole page update. Woh. Let's do this!

Leave a comment!

0
Login or Register to join the conversation
Cat in space

"Houston: no signs of life"
Start the conversation!

This course is also built to work with Vue 3!

What JavaScript libraries does this tutorial use?

// package.json
{
    "devDependencies": {
        "@symfony/webpack-encore": "^0.30.0", // 0.30.2
        "axios": "^0.19.2", // 0.19.2
        "bootstrap": "^4.4.1", // 4.5.0
        "core-js": "^3.0.0", // 3.6.5
        "eslint": "^6.7.2", // 6.8.0
        "eslint-config-airbnb-base": "^14.0.0", // 14.1.0
        "eslint-plugin-import": "^2.19.1", // 2.20.2
        "eslint-plugin-vue": "^6.0.1", // 6.2.2
        "regenerator-runtime": "^0.13.2", // 0.13.5
        "sass": "^1.29.0", // 1.29.0
        "sass-loader": "^8.0.0", // 8.0.2
        "vue": "^2.6.11", // 2.6.11
        "vue-loader": "^15.9.1", // 15.9.2
        "vue-template-compiler": "^2.6.11", // 2.6.11
        "webpack-notifier": "^1.6.0" // 1.8.0
    }
}
userVoice