A New Vue On JavaScript30 - 06 Type Ahead
Tags: anewvueonjs30, vue, javascript30, javascript
Published: 2018-11-02 15:27:16

---
title: A New Vue On JavaScript30 - 06 Type Ahead
published: true
tags: ANewVueOnJS30,Vue,JavaScript30,JavaScript
canonical_url: https://davefollett.io/2018/11/02/a-new-vue-on-javascript30-06-type-ahead/
cover_image: https://davefollett.io/2018/11/02/a-new-vue-on-javascript30-06-type-ahead/cover-type-ahead.jpg
series: A New Vue On JavaScript30
---

This article is part of the [A New Vue On JavaScript30](/t/anewvueonjs30) series that explores re-implementing Wes Bos’s ([@wesbos](https://twitter.com/wesbos)) [#JavaScript30](https://JavaScript30.com) projects using [Vue](https://vuejs.org). 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](https://davefollett.io/2018/11/02/a-new-vue-on-javascript30-06-type-ahead/js30-type-ahead.gif)

## 🔑 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](https://github.com/davefollett/JavaScript30/blob/master/00%20-%20Getting%20Started/index-VUE.html) from my [getting started](/davefollett/a-new-vue-on-javascript30---getting-started-4o61) 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](https://davefollett.io/2018/11/02/a-new-vue-on-javascript30-06-type-ahead/js30-to-vue-locations.gif)

- 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.

{% gist https://gist.github.com/davefollett/d07e22090d472a2aa008127395cbacca %}

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.

{% gist https://gist.github.com/davefollett/2ee3d751da434a34e1fd2ed124d76d69 %}

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.

{% gist https://gist.github.com/davefollett/bf940ed29f19b1ba63cbe1dbf77134e4 %}

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](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) and the default information when `searchValue` is [falsy](https://developer.mozilla.org/en-US/docs/Glossary/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)](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model). 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

{% codesandbox yvyqm83lnz initialpath=06%20-%20Type%20Ahead%2Findex-VUE.html module=%2F06%20-%20Type%20Ahead%2Findex-VUE.html %}

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](https://codesandbox.io/s/rmmqxvqlrq) and shared it with a friend and on the [Vue Land Discord](https://vue-land.js.org/) 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](https://vuejs.org/v2/guide/conditional.html) in the [Official Vue Documentation](https://vuejs.org/v2/guide/).
- For more information about the `v-html` directive, you can read about it [here](https://vuejs.org/v2/guide/syntax.html#Raw-HTML) in the [Official Vue Documentation](https://vuejs.org/v2/guide/).

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

- [#JavaScript30’s 06 - Type Ahead](https://github.com/davefollett/JavaScript30/blob/master/06%20-%20Type%20Ahead/index-FINISHED.html)
- [A New Vue On JavaScript30’s 06 - Type Ahead](https://github.com/davefollett/JavaScript30/blob/master/06%20-%20Type%20Ahead/index-VUE.html)

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](https://github.com/davefollett/JavaScript30) of the official [#JavaScript30 GitHub repository](https://github.com/wesbos/JavaScript30) which is located at:

- [https://github.com/davefollett/JavaScript30](https://github.com/davefollett/JavaScript30)

## 🔜 Up Next

Next in the [A New Vue On JavaScript30](/t/anewvueonjs30) series is:

{% link /davefollett/a-new-vue-on-javascript30---08-fun-with-html5-canvas-86m %}