or how to implement an autocomplete with VueJS + VuetifyJS

Image for post
Image for post

Today I want to share me recent learnings on implementing an autocomplete with VuetifyJS using the fetch API.

Therefore I added this tag to my page

<v-combobox
v-model.trim="selectedPlace"
:items="foundPlaces"
:loading="isPlacesLoading"
:search-input.sync="searchPlace"
hide-no-data
hide-selected
label="Ort"
clearable
:rules="nameRules"
/>

that should render like this

Image for post
Image for post

The code handling the search using the AbortController:

watch: {
async searchPlace (name) {
if (!name) return
if (this.isPlacesLoading) {
this.searchFetchController.abort()
}
this.searchFetchController = new ()
this.isPlacesLoading = true
const url = `http://api.geonames.org/searchJSON?q=${name}&username=demo`
try {
const response = await fetch(url, {
method: 'GET', signal: this.searchFetchController.signal
})
const responseAsJson = await response.json()
this.foundPlaces = responseAsJson.geonames
.map(({ geonameId, name, countryName, ...rest }) => ({ value: geonameId, text: `${name} (${countryName})`, ...rest }))
this.isPlacesLoading = false
} catch (exception) {
if (exception instanceof ) { // ignore aborts
} else {
this.isPlacesLoading = false
.log(exception)
}
}
},

So what am I doing here?

The AbortController, as the name suggests, can be used to abort something, here a fetch request. To use it you have to create an instance like above:

this.searchFetchController = new ()

Now this controller can be used to abort multiple requests at once by adding its signal instance to each request — here only one request.

const response = await fetch(url, {
method: 'GET', signal: this.searchFetchController.signal
})

In case of aborting a request you simply have to call the abort method of the controller, signaling all configured requests, that they should abort.

this.searchFetchController.abort()

Doing this throws a DOMException that should be catched.

} catch (exception) {
if (exception instanceof ) { // ignore aborts
} else {
this.isPlacesLoading = false
.log(exception)
}
}

The interesting thing here is that this catch handles the previous made request and is thrown when we return from the method call. So it should not update isPlacesLoading otherwise it would overwrite it from the current call.

The other thing to mention here is that you always need a fresh Controller, when the actual has receives an abort.

See you

Developer since the 80'th, working at Forschungszentrum Jülich (http://www.fz-juelich.de) …

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store