adev/src/content/guide/aria/autocomplete.md
An accessible input field that filters and suggests options as users type, helping them find and select values from a list.
<docs-tab-group> <docs-tab label="Basic"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/autocomplete/src/basic/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/autocomplete/src/basic/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/autocomplete/src/basic/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/autocomplete/src/basic/app/app.css"/> </docs-code-multifile> </docs-tab> <docs-tab label="Material"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/autocomplete/src/basic/material/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/autocomplete/src/basic/material/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/autocomplete/src/basic/material/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/autocomplete/src/basic/material/app/app.css"/> </docs-code-multifile> </docs-tab> <docs-tab label="Retro"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/autocomplete/src/basic/retro/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/autocomplete/src/basic/retro/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/autocomplete/src/basic/retro/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/autocomplete/src/basic/retro/app/app.css"/> </docs-code-multifile> </docs-tab> </docs-tab-group>Autocomplete works best when users need to select from a large set of options where typing is faster than scrolling. Consider using autocomplete when:
Avoid autocomplete when:
Angular's autocomplete provides a fully accessible combobox implementation with:
Users typing partial text expect immediate confirmation that their input matches an available option. Auto-select mode updates the input value to match the first filtered option as users type, reducing the number of keystrokes needed and providing instant feedback that their search is on the right track.
<docs-tab-group> <docs-tab label="Basic"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/autocomplete/src/basic/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/autocomplete/src/basic/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/autocomplete/src/basic/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/autocomplete/src/basic/app/app.css"/> </docs-code-multifile> </docs-tab> <docs-tab label="Material"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/autocomplete/src/basic/material/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/autocomplete/src/basic/material/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/autocomplete/src/basic/material/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/autocomplete/src/basic/material/app/app.css"/> </docs-code-multifile> </docs-tab> <docs-tab label="Retro"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/autocomplete/src/basic/retro/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/autocomplete/src/basic/retro/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/autocomplete/src/basic/retro/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/autocomplete/src/basic/retro/app/app.css"/> </docs-code-multifile> </docs-tab> </docs-tab-group>Manual selection mode keeps the typed text unchanged while users navigate the suggestion list, preventing confusion from automatic updates. The input only changes when users explicitly confirm their choice with Enter or a click.
<docs-tab-group> <docs-tab label="Basic"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/autocomplete/src/manual/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/autocomplete/src/manual/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/autocomplete/src/manual/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/autocomplete/src/manual/app/app.css"/> </docs-code-multifile> </docs-tab> <docs-tab label="Material"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/autocomplete/src/manual/material/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/autocomplete/src/manual/material/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/autocomplete/src/manual/material/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/autocomplete/src/manual/material/app/app.css"/> </docs-code-multifile> </docs-tab> <docs-tab label="Retro"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/autocomplete/src/manual/retro/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/autocomplete/src/manual/retro/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/autocomplete/src/manual/retro/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/autocomplete/src/manual/retro/app/app.css"/> </docs-code-multifile> </docs-tab> </docs-tab-group>Highlight mode allows the user to navigate options with arrow keys without changing the input value as they browse until they explicitly select a new option with Enter or click.
<docs-tab-group> <docs-tab label="Basic"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/autocomplete/src/highlight/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/autocomplete/src/highlight/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/autocomplete/src/highlight/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/autocomplete/src/highlight/app/app.css"/> </docs-code-multifile> </docs-tab> <docs-tab label="Material"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/autocomplete/src/highlight/material/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/autocomplete/src/highlight/material/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/autocomplete/src/highlight/material/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/autocomplete/src/highlight/material/app/app.css"/> </docs-code-multifile> </docs-tab> <docs-tab label="Retro"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/autocomplete/src/highlight/retro/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/autocomplete/src/highlight/retro/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/autocomplete/src/highlight/retro/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/autocomplete/src/highlight/retro/app/app.css"/> </docs-code-multifile> </docs-tab> </docs-tab-group>Angular Aria integrates seamlessly with the signal-based Signal Forms API. You can encapsulate complex inputs into reusable custom control components implementing FormValueControl.
The following example demonstrates a country selector component implementing FormValueControl<string>, bound to the parent form using [formField] and protected by schema validation rules.
The autocomplete pattern can be tested using a combination of ComboboxHarness and ListboxHarness from @angular/aria/combobox/testing and @angular/aria/listbox/testing.
Here is an example of how to use the harnesses to test an autocomplete component:
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {HarnessLoader} from '@angular/cdk/testing';
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
import {ComboboxHarness} from '@angular/aria/combobox/testing';
import {ListboxHarness} from '@angular/aria/listbox/testing';
import {MyAutocompleteComponent} from './my-autocomplete'; // Your component
describe('MyAutocompleteComponent', () => {
let fixture: ComponentFixture<MyAutocompleteComponent>;
let loader: HarnessLoader;
beforeEach(async () => {
TestBed.configureTestingModule({
imports: [MyAutocompleteComponent],
});
fixture = TestBed.createComponent(MyAutocompleteComponent);
await fixture.whenStable();
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should filter options based on input', async () => {
const combobox = await loader.getHarness(ComboboxHarness);
// Type in the input to trigger filtering
await combobox.setValue('ap');
expect(await combobox.isOpen()).toBe(true);
// Get the listbox harness from the popup
const listbox = await combobox.getPopupWidget(ListboxHarness);
const options = await listbox.getOptions();
// Verify options are filtered (e.g., 'Apple', 'Apricot')
expect(options.length).toBe(2);
expect(await options[0].getText()).toBe('Apple');
// Select the first option
await options[0].click();
// Verify the input value is updated and popup is closed
expect(await combobox.isOpen()).toBe(false);
expect(await combobox.getValue()).toBe('Apple');
});
});
The ngCombobox directive is applied directly onto the editable text <input> or <textarea> to manage keyboard triggers and popover states.
| Property | Type | Default | Description |
|---|---|---|---|
disabled | boolean | false | Disables the combobox |
softDisabled | boolean | true | Focusable when disabled |
inlineSuggestion | string | undefined | undefined | Displays an inline completion suggestion for autocomplete modes |
| Property | Type | Default | Description |
|---|---|---|---|
value | ModelSignal<string> | '' | Two-way bindable value of the input using [(value)] |
expanded | ModelSignal<boolean> | false | Two-way bindable expanded state of the popup using [(expanded)] |
A structural directive applied to <ng-template> to mark the container used as the popup.
| Property | Type | Description |
|---|---|---|
combobox | Combobox | Required reference to the parent Combobox |
Applied to the popup content container to bridge active-descendant focus changes to the input trigger.
| Property | Type | Description |
|---|---|---|
activeDescendant | string | undefined | The ID of the currently active descendant (bound to listbox.activeDescendant()) |
Autocomplete suggestion lists use the standard standalone listbox directives.
| Property | Type | Default | Description |
|---|---|---|---|
selectionMode | 'follow' | 'explicit' | 'follow' | In manual/explicit mode, updates are committed explicitly on click/Enter rather than following focus |
focusMode | 'roving' | 'activedescendant' | 'roving' | Set to 'activedescendant' so browser focus stays on the trigger input |
tabIndex | number | 0 | Set to -1 to prevent keyboard tab focus from entering the popup listbox container |
| Property | Type | Description |
|---|---|---|
value | ModelSignal<any[]> | Two-way bindable array of selected values using [(value)] |
Autocomplete uses standard standalone Listbox and Option directives. See the Listbox documentation for advanced options.