Skip to content

Autocomplete

SAutocomplete is an input with suggestions from search results. Unlike SSelect with the searchable prop, the options come from outside and change on every keystroke: the component does not filter options again, so results of fuzzy search, transliteration, and index search get through.

It is built on Reka UI Combobox: combobox/listbox/option roles, keyboard navigation, and a portaled panel. The label, hint and error message come from SFormField.

Two v-models

The value and the query are separate: v-model holds the selected value, v-model:search holds what the user typed. The app searches by the latter, usually with a debounce.

v-model:search receives only typed text: the label of the selected option and the text reset on panel close are not written there, so there is no extra request for the label, and the typed text does not disappear when the user leaves the field without picking anything. Writing to it from outside puts the text into the field — this is how a saved form is restored.

The label of the selected value comes from the selected-label prop: after a selection the suggestion list is usually empty, so the label cannot be taken from it. While no value is selected, selected-label does not touch the field text.

The select event fires on every suggestion pick, by mouse or keyboard. Unlike update:modelValue, it also fires when the same suggestion is picked again, so the app can repeat a check in a "picked → server rejected → picked again" scenario.

The Home and End keys stay with the input and move the caret within the text, not through the suggestion list. The arrow keys navigate the list.

Focus inside the component is not leaving the field

Clicking a suggestion does not fire blur: a "left the field without picking" handler would run before the selection, and if it changed the list, the item would vanish between mouse down and mouse up. blur is emitted only when focus leaves the component.

Custom option row

The #option slot replaces the row content, since a suggestion is rarely a single line of text. The #prepend slot places an element inside the frame on the left, usually an icon or a country flag.

Loading and empty results

While a request is in flight, loading shows an indicator instead of the list. When there are no suggestions, the panel shows a placeholder: the empty-text prop sets its text, the #empty slot sets its markup.

SSelect or SAutocomplete

SituationComponent
The full list of options is known in advanceSSelect
Many options, search over a ready listSSelect with searchable
Options come from the server and change on every keystrokeSAutocomplete
Fuzzy search, transliteration, or index search is neededSAutocomplete

API

Props

NameTypeDefaultDescription
options*{ label: string; value: string; disabled?: boolean }[]requiredCurrent suggestions: the result of the application-side search. The list is not filtered again; whatever arrives is shown (fuzzy search, transliteration, index search).
selected-labelstringundefinedLabel of the selected value. A separate prop, because after a selection the suggestion list is usually empty and the label cannot be taken from it.
loadingbooleanfalseA request is in flight: a loading indicator is shown instead of the list.
empty-textstringundefinedText shown when there are no suggestions (defaults to the locale dictionary).
labelstringundefinedField label (rendered via SFormField/SLabel).
hintstringundefinedHint below the field.
errorstringundefinedError message. When set, the field is marked invalid.
invalidbooleanfalseExplicitly marks the field invalid (in addition to error).
requiredbooleanfalseRequired field: a * marker next to the label.
disabledbooleanfalseDisables the field.
placeholderstringundefinedPlaceholder text in an empty field.
idstringundefinedInput id. Generated when not set (SSR-safe).
size"md" | "sm" | "lg""md"Field size: sm (32px), md (40px) or lg (48px).
squarebooleanundefinedSquare corners: removes the rounding of the frame and the suggestion panel.
clearablebooleantrueShows the clear button: it resets both the selection and the query text.
clear-iconstring"x"Clear button icon: a registry name or a raw path.
clear-labelstringundefinedAccessible name of the clear button (defaults to the locale dictionary).
iconstringundefinedLeading icon inside the field (a registry name or a raw path), drawn on the left.
aria-labelstringundefinedAccessible name of the field (when there is no visible label).
max-heightstring | numberundefinedMaximum height of the suggestion panel (20rem by default). A number means pixels. The panel also never grows past the free space to the window edge; the smaller of the two wins.
flatbooleanundefinedRemoves the shadow. Overridden by the elevation prop when it is set.
elevation0 | 1 | 2 | 3 | 4 | 5undefinedShadow level 0–5 (scale); 0 means no shadow. Overrides flat.
model-valuestringundefinedSelected value: the suggestion's value. Two-way binding via v-model.
searchstring""The user's query: what they typed. The application searches by it, usually debounced, and passes the result back into options. The component writes only typed text here (and an empty string from the clear button): the selected label and the reset on panel close do not get here, otherwise the query would be indistinguishable from text the component inserted itself. Writing from outside puts the text into the input, which is how a saved form is restored.

Events

NameSignatureDescription
update:modelValue(value: string | undefined) => voidEmitted when modelValue changes. Used for two-way binding (v-model).
update:search(value: string) => voidEmitted when search changes. Used for two-way binding (v-model:search).
clear() => voidThe value and the query text were cleared with the clear button.
select(option: SAutocompleteOption) => voidThe user selected a suggestion with the mouse or keyboard. Fires on every selection, including re-selecting the same suggestion, when update:modelValue stays silent because the value did not change.

Slots

NameDescription
prependContent at the start of the field, inside the frame (icon, country flag, button).
appendContent at the end of the field, inside the frame.
optionList row instead of the label. Receives the scoped props { option, index }.
emptyPanel content when there are no suggestions.
loadingPanel content while a request is in flight.