Component
Autocomplete
<dom-autocomplete>A styled datalist-like text input: free text stays separate from selected suggestions.
Playground
Try every prop live
Autocomplete playground
Edit props in the inspector — type to filter suggestions and test the free-text path.
- Ada Lovelace
- Grace Hopper
- Katherine Johnson
Playground.vuevue
<script setup>
import { reactive } from 'vue';
import { DomAutocomplete } from '@getdom/studio/vue';
const data = reactive({
"modelValue": "",
"id": "",
"name": "",
"label": "",
"description": "",
"placeholder": "Search people",
"required": false,
"disabled": false,
"readOnly": false,
"invalid": false,
"errors": {},
"visible": true,
"validators": [],
"validateOnBlur": true,
"chrome": "field",
"options": [
{
"value": "1",
"label": "Ada Lovelace",
"email": "ada@example.com"
},
{
"value": "2",
"label": "Grace Hopper",
"email": "grace@example.com"
},
{
"value": "3",
"label": "Katherine Johnson",
"email": "katherine@example.com"
}
],
"placement": "bottom",
"floatingMode": "viewport",
"loading": false
});
</script>
<template>
<DomAutocomplete
v-bind="data"
@update:modelValue="data.modelValue = $event"
/>
</template>Demo
Search people
v-model is the typed text. @select receives the original option object when a suggestion is chosen.
- Ada Lovelace
- Grace Hopper
- Katherine Johnson
Typed text: —
Selected item: —
SearchPeople.vuevue
<script setup>
import { DomAutocomplete } from '@getdom/studio/vue';
import { ref } from 'vue';
const text = ref('');
const selected = ref(null);
const people = [
{ value: '1', label: 'Ada Lovelace', email: 'ada@example.com' },
{ value: '2', label: 'Grace Hopper', email: 'grace@example.com' },
{ value: '3', label: 'Katherine Johnson', email: 'katherine@example.com' },
];
function onSelect(event) {
selected.value = event.item;
}
</script>
<template>
<div class="flex w-full max-w-sm flex-col gap-2">
<DomAutocomplete
v-model="text"
:options="people"
placeholder="Search people"
class="w-full"
@select="onSelect"
/>
<p class="text-xs text-muted-fg">Typed text: <code class="text-fg">{{ text || '—' }}</code></p>
<p class="text-xs text-muted-fg">Selected item: <code class="text-fg">{{ selected?.email || '—' }}</code></p>
</div>
</template>
Demo
Server-loaded suggestions
@query lets the parent fetch suggestions and pass the current server results back through options.
Suggestions are fetched by the parent in response to @query.
Text value: Empty
ServerLoadedPeople.vuevue
<script setup>
import { ref } from 'vue';
import { DomAutocomplete } from '@getdom/studio/vue';
import { searchPeople } from '../../_shared/serverLookup.js';
const value = ref('');
const options = ref([]);
const loading = ref(false);
let requestId = 0;
async function queryPeople(query) {
const currentRequest = ++requestId;
if (!query.trim()) {
options.value = [];
loading.value = false;
return;
}
loading.value = true;
const results = await searchPeople(query);
if (currentRequest !== requestId) return;
options.value = results.map((person) => ({
...person,
value: person.label,
description: person.email,
}));
loading.value = false;
}
</script>
<template>
<div class="grid w-full max-w-md gap-3">
<DomAutocomplete
v-model="value"
:options="options"
:loading="loading"
label="Search people"
description="Suggestions are fetched by the parent in response to @query."
placeholder="Type a name"
class="w-full"
@query="queryPeople"
>
<template #item="{ item }">
<span class="block min-w-0">
<span class="block truncate font-medium">{{ item.label }}</span>
<span class="block truncate text-xs text-muted-fg">{{ item.description }}</span>
</span>
</template>
</DomAutocomplete>
<p class="rounded-2xl border border-border bg-secondary/40 p-3 text-xs text-muted-fg">
Text value: <code class="font-mono text-fg">{{ value || 'Empty' }}</code>
</p>
</div>
</template>
Usage
Plain HTML
Use the headless custom element when you want autocomplete in plain HTML or another framework. The headless page includes a copyable HTML and JavaScript example.
View headless autocompleteProps
Props
| Name | Type | Default | Description |
|---|---|---|---|
| v-model | string | — | Current text in the input. |
| options | Array<{ value, label, ...meta }> | string[] | [] | Suggestions. May be replaced as query results arrive. |
| placeholder | string | 'Search...' | Input placeholder. |
| floatingMode | 'viewport' | 'anchor' | 'viewport' | Choose whether suggestions stay in the browser or follow the input while scrolling. |
| loading | boolean | false | Show an inline spinner while async suggestions are being fetched. |
Events
update:modelValueFired as the text changes.queryFired as the user types. Use this to fetch suggestions.selectFired when a suggestion is chosen. Receives the original item plus value, label, text, and query.commitFired when Enter commits the current text.