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.
🔑 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.
- The HTML section was placed inside the root
<div id="app">
- The
endpoint
andcities
variables were placed into thedata
section - The
numberWithCommas()
function was placed into themethods
section - The
findMatches()
anddisplayMatches()
functions were placed into thecomputed
section - The
fetch()
call that executed on page load was placed into themounted
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.
- For more information about conditional rendering and using the
<template>
element as an invisible wrapper, you can read about it here in the Official Vue Documentation. - For more information about the
v-html
directive, you can read about it here in the Official Vue Documentation.
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 is:
Top comments (2)
Great work Dave! I am learning Vue and your Vue version of JavaScript30 will be a sure place to go. Keep going.
Thank you for the kind words. Reach out if you have any questions. Good luck!