A text field that suggests options as you type. It shares GogDropdownBase with Select — the same option accessors, placement, float label, error state and ControlValueAccessor — but its trigger is a real <input>, which is what makes it a separate control rather than a mode of the select.
Two things shape how the panel behaves before a query even runs. openOnFocus21.3.1 — on by default — opens the panel with the full option list the moment the field is focused, instead of waiting for minLength characters: for a short, known list that is the difference between a combobox and a text field the user has to guess at. Turn it off per instance, or app-wide with GOG_CONFIG.autocomplete.openOnFocus, to keep the older behaviour of showing nothing until something is typed.
gogLoadMore21.3.1 fires when the panel is scrolled to its end. Fetch the next page and append it to options — that is how a large or server-backed source is paged, with no virtual scroller involved.
gogSearch is debounced (searchDebounce, 300 ms by default), so a lookup fires once the typing settles rather than on every keystroke. Set [filterLocal]="false" alongside it: the server has already filtered, and filtering its answer a second time against the same query is the classic double-filtering bug — it silently drops rows the server matched on a field this component cannot see.
This demo fakes a 400 ms round trip. It also matches on the country, which local filtering would throw away — type germany to see it.
optionLabel, optionValue and optionDisabled take a property path (dot-paths included) or a function. Set [optionValue]="null" and the control hands back the option object — the same reference you passed in — instead of an id.
value = null
<!-- optionValue="null" hands back the option object itself, not an id. --><gog-autocompletelabel="City"optionLabel="name"
[optionValue]="null"
[options]="cities"
[(value)]="cityObject"
/>
Custom suggestion rows
A gogDropdownOption template replaces one row, with the option itself plus selected, disabled and the resolved label in its context — so a custom row can decorate the label rather than re-derive it.
On by default, the field always ends up reflecting a real selection: editing is treated as transient, so value survives keystrokes and Escape or blur snaps the text back to it. Turn it off for a create-as-you-type flow — the text is then left alone on blur and value is dropped as soon as it stops matching, so the two never disagree. Read what was typed from gogSearch, not from value.
<!-- forceSelection="false": what was typed is itself meaningful. --><gog-autocompletelabel="Tag"
[forceSelection]="false"
[options]="cities"
(gogSearch)="draft.set($event)"
[(value)]="freeText"
/>
Accessibility
The <input> keeps DOM focus the whole time and the highlighted suggestion is pointed at with aria-activedescendant — where a listbox would move focus onto the option itself. That is the difference that makes this a combobox rather than a select, and it is why typing keeps working while the panel is open.
Arrow keys move the highlight, Enter picks it, Escape closes the panel. Give the field a label or an ariaLabel; use inputId if you are wiring your own <label for="…">.
Virtualized options — virtualize21.13.0
[virtualize]="true" renders only the rows in view. Unwindowed, 10 000 options build 10 000 DOM rows to show about six — measured in Chrome, 512 ms before the panel appears, against 21 ms windowed on the same data. The scrollbar looks the same either way, because spacers stand in for the rows that are not there.
10 000 cities. Focus the field and scroll the panel, or press End.
Off by default, and never switched on at some row count. A windowed list behaves differently in ways nothing about the data predicts: Ctrl+F finds only the rendered rows, and CSS targeting :last-child matches the last rendered row. A threshold would make that depend on how much data happened to arrive, so set it per field, or app-wide with GOG_CONFIG.dropdown.virtualize.
The announced count stays honest: the aria-setsize and aria-posinset carry the real list, so a screen reader hears "10 000 items" rather than "20". Arrow keys walk the whole list — End reaches the last option.
Focus never moves, which is the one way this differs from the select and the multiselect. Their windowed lists hand focus back to the trigger when a focused row scrolls away; a combobox keeps focus in its input the whole time, so there is nothing to hand back.
gog-table's virtualize is a different story under the same name: table rows vary in height, so it measures as it goes — see the Table page.
Not the same thing as gogLoadMore, and the two compose. The server-backed suggestions above keep the number of records the server sends small; virtualize keeps the number of rows the browser builds small. A gogLoadMore list that has loaded 10 000 records still stamps 10 000 rows without it — neither implies the other, and a list long enough to want one usually wants both.
API Reference
Inputs — autocomplete's own
Name
Type
Default
Description
openOnFocus21.3.1
boolean | undefined
undefined
Whether focusing the field opens the panel immediately with the full option list, rather than waiting for minLength characters. Unset, falls back to GOG_CONFIG.autocomplete.openOnFocus, then to true.
value
TValue
null
The selected value — whatever optionValue resolves to. Two-way bindable with [(value)].
filterLocal
boolean
true
Whether options are narrowed in the browser as you type. Turn it OFF when gogSearch fetches an already-filtered list: filtering that answer a second time is the classic double-filtering bug, and it silently drops rows the server matched on a field this component cannot see.
minLength
number
GOG_CONFIG.autocomplete.minLength ?? 1
How many characters before the panel opens at all.
searchDebounce
number
GOG_CONFIG.autocomplete.searchDebounce ?? 300
Milliseconds of quiet before gogSearch fires. 0 emits on every keystroke.
loading
boolean
false
Shows a spinner in the trailing slot, for a server-backed source still fetching.
emptyMessage
string
'No matches'
Shown in place of the list when nothing matches.
forceSelection
boolean
true
On, the field always ends up reflecting a real selection — editing is transient and Escape or blur snaps the text back. Off, the typed text is itself meaningful (a create-as-you-type flow): it survives blur and value is dropped as soon as it stops matching, so the two never disagree.
inputId
string
''
id for the inner <input>, for an external <label for="…">.
ripple21.6.1
boolean | undefined
undefined
Press ripple on each option row in the panel. Unset, falls back to GOG_CONFIG.ripple.enabled, which is off by default; setting it here wins over the app-wide value in both directions.
virtualize21.13.0
boolean | undefined
GOG_CONFIG.dropdown.virtualize ?? false
Renders only the suggestion rows in view — about twenty in the DOM whatever the list holds. Off by default and never switched on at a row count: Ctrl+F finds only rendered rows and :last-child matches the last rendered one. aria-setsize/aria-posinset keep the announced count real.
Inputs — shared with Select
These come from GogDropdownBase and behave exactly as they do on Select. The one exception is filter: an autocomplete's trigger already is the search box, so the panel never gets a second one — filterMatch still applies, though, since it plugs into filterLocal's own matching rather than the panel's search box.
Name
Type
Default
Description
options
TOption[]
[]
The suggestions. Your own objects.
optionLabel
string | ((o: TOption) => string)
'name'
Property path (dot-paths included) or function producing an option’s label.
optionValue
string | ((o: TOption) => unknown) | null
'id'
What the control emits. null emits the option object itself.
Panel placement. appendToBody renders it into <body> so an overflow-clipped ancestor cannot cut it off.
Outputs
Name
Payload
Description
gogSearch
string
The current query, debounced. Wire a server-side lookup to this.
gogLoadMore21.3.1
void
The panel was scrolled to the end. Fetch the next page and append it to options — this is how a large or server-backed option source is paged without a virtual scroller.
valueChange
TValue
Emitted when the selection changes. Comes from the value model input.
Content slots
Directive
Context
Description
gogDropdownOption
$implicit, selected, disabled, label
Replaces one suggestion row.
Global Configuration
Set any of these once with provideGogConfig() instead of repeating them on every instance — an instance's own input still wins when it sets one itself. See Global Configuration for the full reference.
GOG_CONFIG.control.size
GOG_CONFIG.control.errorDisplay
GOG_CONFIG.control.clearable
GOG_CONFIG.floatLabel.variant
GOG_CONFIG.floatLabel.showPlaceholder
GOG_CONFIG.dropdown.appendToBody
GOG_CONFIG.dropdown.direction
GOG_CONFIG.dropdown.virtualize
GOG_CONFIG.ripple.enabled
GOG_CONFIG.autocomplete.minLength
GOG_CONFIG.autocomplete.searchDebounce
GOG_CONFIG.autocomplete.openOnFocus
GOG_CONFIG.spinner.component — the spinner loading draws, which has no input of its own
GOG_CONFIG.spinner.variant — the same spinner, when no component is set
GOG_CONFIG.labels.clearSelection
This site is not on the default here. The library ships ripple.enabled as false; these docs set it to true app-wide so the demos above actually show the press feedback. In a fresh app you get no ripple until you ask for one — the droplet button in the header switches this site between the two, and it is on right now.
Styling Tokens
Every CSS custom property the autocomplete paints with. Override any of them — on a single instance, a subtree, or a theme — to restyle it. See the Theming guide for the full token-layering model, or the Theme Generator to tweak these live.
A seed for the first frame rather than the row height — the component measures a real row and corrects itself, which is also what places the panel above or below the field. And the gap between the field and its panel.
--gog-autocomplete-empty-color / -spinner-size
The "nothing found" message and the loading spinner.