AppAutocomplete
Pick one value from a long or remote list by typing — the field narrows as you go.
<app-autocomplete label="City" name="city">…</app-autocomplete>An autocomplete lets a user pick a single value from a list too long to scroll — a city, a customer, a product — by typing toward it. The field filters as they type, so they land on the right option in a keystroke or two instead of hunting through a giant dropdown.
Its look and behaviour come from the shared @webority/theme and the underlying <wui-autocomplete> element, so the Razor <app-autocomplete> and the React <AppAutocomplete> render identically on every Webority surface.
Playground
Every attribute, live. Each change re-renders the real tag helper on the server, so the markup underneath is the exact call that produced the field above it.
<app-option> children (static filter); checked, it's given remote="true" plus a page-side search handler, as wired below for this preview.Static filter
Pass an options array and the field filters it client-side. Best when the whole list is already in memory — up to a few hundred rows.
<app-option> children; the field matches as the user types.Show code
<app-autocomplete label="City" name="city" placeholder="Type a city…">
<app-option value="mumbai">Mumbai</app-option>
<app-option value="delhi">Delhi</app-option>
<app-option value="pune">Pune</app-option>
<!-- … -->
</app-autocomplete>
Remote search
Pass an async loadOptions instead of options and the field becomes a search box: it debounces typing, shows a spinner while your promise is in flight, then lists what came back.
remote="true", then a page script answers the search event — set .loading, fetch, set .options.Show code
<app-autocomplete remote="true" label="City" name="city"
placeholder="Type to search…" min-chars="1"></app-autocomplete>
<script>
var el = document.getElementById('city');
el.addEventListener('search', function (e) {
el.loading = true;
api.searchCities(e.detail.query).then(function (rows) {
el.options = rows; // [{ value, label }]
el.loading = false;
});
});
</script>
debounce ms (250 by default) after the last keystroke before firing the search event, and won't fire until min-chars characters are typed. That keeps one request per pause instead of one per letter — your API isn't hammered, and the spinner shows only while a real fetch is running.Freeform entry
Set allow-custom="true" and a typed value that matches no option is offered as its own row — pick it (or press Enter) to commit the typed text itself as the value.
change with the typed text as the value; a page script can inspect the committed value however it needs.Show code
<app-autocomplete label="Tag" name="tag" allow-custom="true">
<app-option value="urgent">Urgent</app-option>
<app-option value="billing">Billing</app-option>
</app-autocomplete>
Add "…" row, or by leaving the field (blur) with unmatched text still in it.Sizes
size takes sm or lg (md is the default), matching AppInput and AppSelect so an autocomplete lines up with the fields beside it.
Show code
<app-autocomplete label="Small" name="c" size="sm">…</app-autocomplete> <app-autocomplete label="Medium (default)" name="c">…</app-autocomplete> <app-autocomplete label="Large" name="c" size="lg">…</app-autocomplete>
States
Surface a validation message with error, and mark a mandatory field with required.
Show code
<app-autocomplete label="City" name="city" required="true"
error="Choose a city to continue.">
<app-option value="mumbai">Mumbai</app-option>
<!-- … -->
</app-autocomplete>
When to use
Use it when
- The user picks one value from a list too long to scroll comfortably (dozens or more).
- The list lives on the server — pass loadOptions and fetch only the matches the user types toward.
- Users know the option by name and can type it faster than they can find it in a dropdown.
Reach for something else when
- The user must pick several values. → AppMultiSelect
- There are only 2–5 fixed, exclusive options. → AppRadio
- The list is short and closed (6–15 options). → AppSelect
- It is a free-text search that navigates or filters a page. → AppSearch
Best practices
Every option
The whole surface of the component, one cell per value — including the modes and states a normal example doesn't cover: the loading spinner, an always-empty result set, a rejected search, and every field state.
mode
options — static filter
remote="true" — debounced
loading (forced for the demo)
remote — always empty (type anything)
remote — rejects (falls back to empty)
remote — min-chars="3"
size — every value
size="sm"
size="md"
size="lg"
allow-custom
(default) — no freeform entry
allow-custom="true" — offers an Add "…" row
field state
disabled
required
error
hint
error + hint (error wins)
required + error
value="mumbai" — populated
help / help-label
long option label (overflow)
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
| label | string | — | Field label above the control. |
| name | string | — | Field name — also the element id the label points at. |
| value | string | — | Initial value seed. With asp-for the bound model value is used instead, so a validation redisplay repopulates the field. |
| placeholder | string | Search… | Placeholder text. |
| remote | bool | false | Switches the field to the debounced-fetch mode; wire a search handler. |
| min-chars | int | 0 | Minimum characters before a search fires (React minChars; defaults to 1 automatically when remote is set). |
| debounce | int | 250 | Debounce (ms) for a remote search. Not a typed attribute on this tag helper — passes through to the element as an author attribute. |
| size | string | — | Control size: sm / lg. Omit for the default (md). |
| allow-custom | bool | false | Offers the typed text as an "Add "…"" row when it matches no option (React allowCustom); committing it sets that raw text as the value. |
| disabled | bool | false | Disables the field. |
| required | bool | false | Renders the required asterisk on the label. |
| error | string | — | Validation message; replaces the hint and marks the field invalid. |
| hint | string | — | Helper text below the field when there is no error. |
| help | string | — | Info-tip content shown beside the label. |
| help-label | string | More information | aria-label for the info-tip button (React helpLabel). |
| <app-option> | value, selected | — | Child options for the static list — value attribute + label as inner content. |
| input-class | string | — | Extra classes on the control itself (the wui-autocomplete) — the React className counterpart. The plain class attribute merges onto the .field wrapper instead. |