A New Vue On JavaScript30 - 06 Type Ahead

This article is part of the A New Vue On JavaScript30 series that explores re-implementing Wes Bos’s (@wesbos) #JavaScript30 projects using Vue. Today I will be working with #JavaScript30’s 06 - Type Ahead project. This project uses an input to filter down a list of cities as the user types. In addition to filtering the list, it also highlights the input value in the results. Here is an animated gif of it in action.

#JavaScript30 Finished Type Ahead Project

🔑 Vue Concepts

  • v-for directive
  • v-model directive to create two-way data bindings on form input
  • v-html directive
  • The mounted lifecycle hook
  • Computed Properties

🏗️ Vue Implementation

The first step is the same as my other articles, grab the base starter file from my getting started article and insert the code from the original #JavaScript30 project into their corresponding Vue locations.

Animation of inserting #JavaScript30 code into their corresponding Vue locations

  • The HTML section was placed inside the root <div id="app">
  • The endpoint and cities variables were placed into the data section
  • The numberWithCommas() function was placed into the methods section
  • The findMatches() and displayMatches() functions were placed into the computed section
  • The fetch() call that executed on page load was placed into the mounted function
  • The watch section was not needed so it was removed
  • The <style> section was removed because the stylesheet was pulled in with a <link> tag

Whew, there was a lot going on there but if you have been reading the previous articles, hopefully it’s familiar 😀. Unfortunately, we have quite a bit of work still left to do to get this working. The next step is to adjust the displayMatches() computed property to return an object for each city instead of an HTML list item.

This will make it easier to loop the results of the displayMatches computed property within the HTML area, shown later. Next, I added a v-model directive to create a two-way data bindings on form input to the searchValue variable that I added to the data section.

The last set of changes are numerous and all inside the HTML area. Let’s first take a look at it in full and then break it down.

In the #JavaScript30 version, the unordered list <ul class="suggestions"> displayed default information and then as the user started typing, it was replaced with the matching city information. To do this with Vue, I inserted a v-if / v-else block within <ul class="suggestions"> to conditionally render the matching city information when searchValue is truthy and the default information when searchValue is falsy. You will probably notice I attached the v-if and v-else directives to <template> elements. I did this because Vue directives must be attached to a single element and <template> elements will not be rendered in the Document Object Model (DOM). Within the v-if section, I created matching HTML to the #JavaScript30 project by looping the displayMatches computed property with a v-for directive. On the <span class="name"> element you will see that I used the v-html directive. This was needed because the displayMatches computed property contains strings of HTML and the v-html directive will interpret them as HTML instead of plain text. Finally, the last step was to fill in the v-else section with the unchanged HTML from the #JavaScript30 project.

If you were able to follow and make any sense of all that, please pat yourself on the back and accept this major award: 🏆.

🏁 Putting It All Together

Up until this point, as far as I know, I have been able to create equivalent Vue versions of all the #JavaScript30 projects. But this time I ran into a 🐞 where the capitalization of highlighted text will be wrong as it auto completes if you are using Google Chrome. The 🐞 does not occur when using Firefox or Edge. Did I bump into a bug with Google Chrome or is it with my usage of v-html with Vue’s re-rendering? And why Google Chrome only? I created a CodeSandbox and shared it with a friend and on the Vue Land Discord in an attempt to figure it out. While we had some good theories, we were not able to come to a definitive answer as to why the issue was occurring for Google Chrome only. A few good ideas were also given on ways to restructure the code that probably would avoid the 🐞 but I decided to leave it in because I feel this version is close to matching the overall spirit of #JavaScript30 project. Plus, it’s all my code 😀. I’d still love to hear any feedback on this 🐞, so please let me know if you understand what is causing it.

While I don’t think Vue provides as much as a benefit in this #JavaScript30 project when compared to the others so far, I did find it to be a bigger challenge. It pushed me to learn new Vue techniques, such as the v-html directive and the use of v-if and v-else directives with <template> elements.

Here are links to the #JavaScript30 version and my Vue version:

I hope you enjoyed this article, feel free to message me with any questions, comments, or corrections. All code presented within this series is available in my fork of the official #JavaScript30 GitHub repository which is located at:

🔜 Up Next

Next in the A New Vue On JavaScript30 series will be #JavaScript30’s “08 - Fun with HTML5 Canvas” project. I’ll add a link here when it’s published.

Share