Skip to content

Autocomplete

WxAutocomplete is a text field that suggests. Unlike Select, the model is the text itself — the user may type something that is not in the list, which is what an address line, a city or a tag field needs.

Suggestions from a local list

Value: — free text, not one of the options

Searched on the backend, with custom rows

Last request: · picked:

Usage

vue
<script setup lang="ts">
import { ref } from 'vue'

const city = ref('')
const cities = [{ value: 'Kyiv' }, { value: 'Kharkiv' }, { value: 'Lviv' }]
</script>

<template>
  <wx-autocomplete v-model="city" :options="cities" placeholder="Start typing a city" clearable />
</template>

An option's value is the text that lands in the input when it is picked. Everything else you hang on the option — an id, a whole record — comes back untouched in select and in the option slot.

Searching on the backend

remote turns the local filtering off, so the list is exactly what you put in options. The search event is debounced, min-length holds it back until the term is worth a request, and loading shows that one is in flight:

vue
<script setup lang="ts">
import { ref } from 'vue'

const author = ref('')
const found = ref([])
const loading = ref(false)

async function search(term: string) {
  loading.value = true
  const response = await fetch(`/api/authors?q=${encodeURIComponent(term)}`)
  const authors = await response.json()
  found.value = authors.map((a) => ({ value: a.name, description: a.role, id: a.id }))
  loading.value = false
}
</script>

<template>
  <wx-autocomplete
    v-model="author"
    :options="found"
    :loading="loading"
    :min-length="2"
    remote
    @search="search"
    @select="onPick"
  />
</template>

Picking a suggestion does not fire another search — the field would otherwise ask the backend for the text it has just been given.

Custom rows

The option slot replaces the default two lines. It receives the whole option, extra fields included:

vue
<template>
  <wx-autocomplete v-model="author" :options="found" remote @search="search">
    <template #option="{ option }">
      <span class="row">
        <wx-icon name="user" />
        {{ option.value }}
        <small>#{{ option.id }} · {{ option.description }}</small>
      </span>
    </template>
  </wx-autocomplete>
</template>

Props

PropTypeDefaultDescription
modelValuestring''The text in the field
optionsAutocompleteOption[][]{ value, label?, description?, disabled? }
remotebooleanfalseDo not filter locally
debouncenumber300Quiet time before search fires
loadingbooleanfalseShows a spinner
loadingTextstring'Searching…'Shown while the first response is awaited
emptyTextstring'Nothing found'Shown when nothing matches
minLengthnumber0Characters needed before searching
clearablebooleanfalseButton that empties the field
openOnFocusbooleantrueOpen the list on focus
teleportbooleantrueRender the list in a portal
placeholderstringPlaceholder
size'sm' | 'md' | 'lg''md'Control height
status'default' | 'success' | 'warning' | 'error''default'Validation state
disabledbooleanfalseDisables the control
namestringField name for a plain form post
idstringgeneratedOverrides the id the label points at; WxFormItem supplies one
ariaLabelstringLabel when there is no visible one

Events: update:modelValue, change (string), search (string, debounced), select (AutocompleteOption), clear, open, close.

Slots: option ({ option }), prefix, suffix.

Inside a FormItem the field takes its size, its disabled state and its validation status from the form, exactly like the other controls.

Released under the MIT License.