adev/src/content/guide/aria/select.md
A pattern that combines a combobox with a listbox to create single-selection dropdowns with keyboard navigation and screen reader support.
<docs-tab-group> <docs-tab label="Basic"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/select/src/icons/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/select/src/icons/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/select/src/icons/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/select/src/icons/app/app.css"/> </docs-code-multifile> </docs-tab> <docs-tab label="Material"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/select/src/icons/material/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/select/src/icons/material/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/select/src/icons/material/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/select/src/icons/material/app/app.css"/> </docs-code-multifile> </docs-tab> <docs-tab label="Retro"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/select/src/icons/retro/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/select/src/icons/retro/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/select/src/icons/retro/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/select/src/icons/retro/app/app.css"/> </docs-code-multifile> </docs-tab> </docs-tab-group>The select pattern works best when users need to choose a single value from a familiar set of options.
Consider using this pattern when:
Avoid this pattern when:
The select pattern combines Combobox and Listbox directives to provide a fully accessible dropdown with:
Users need a standard dropdown to choose from a list of values. A combobox paired with a listbox provides the familiar select experience with full accessibility support.
<docs-tab-group> <docs-tab label="Basic"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/select/src/basic/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/select/src/basic/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/select/src/basic/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/select/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/select/src/basic/material/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/select/src/basic/material/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/select/src/basic/material/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/select/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/select/src/basic/retro/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/select/src/basic/retro/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/select/src/basic/retro/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/select/src/basic/retro/app/app.css"/> </docs-code-multifile> </docs-tab> </docs-tab-group>Text input is prevented by applying the ngCombobox directive directly onto a non-interactive host element (such as a div or a button) instead of an <input>. Users interact with the dropdown using arrow keys and Enter, just like a native select element.
Options often need visual indicators like icons or badges to help users identify choices quickly. Custom templates within options allow rich formatting while maintaining accessibility.
<docs-tab-group> <docs-tab label="Basic"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/select/src/icons/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/select/src/icons/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/select/src/icons/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/select/src/icons/app/app.css"/> </docs-code-multifile> </docs-tab> <docs-tab label="Material"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/select/src/icons/material/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/select/src/icons/material/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/select/src/icons/material/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/select/src/icons/material/app/app.css"/> </docs-code-multifile> </docs-tab> <docs-tab label="Retro"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/select/src/icons/retro/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/select/src/icons/retro/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/select/src/icons/retro/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/select/src/icons/retro/app/app.css"/> </docs-code-multifile> </docs-tab> </docs-tab-group>Each option displays an icon alongside the label. The selected value updates to show the chosen option's icon and text, providing clear visual feedback.
Selects can be disabled to prevent user interaction when certain form conditions aren't met. The disabled state provides visual feedback and prevents keyboard interaction.
<docs-tab-group> <docs-tab label="Basic"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/select/src/disabled/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/select/src/disabled/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/select/src/disabled/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/select/src/disabled/app/app.css"/> </docs-code-multifile> </docs-tab> <docs-tab label="Material"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/select/src/disabled/material/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/select/src/disabled/material/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/select/src/disabled/material/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/select/src/disabled/material/app/app.css"/> </docs-code-multifile> </docs-tab> <docs-tab label="Retro"> <docs-code-multifile preview hideCode path="adev/src/content/examples/aria/select/src/disabled/retro/app/app.ts"> <docs-code header="app.ts" path="adev/src/content/examples/aria/select/src/disabled/retro/app/app.ts"/> <docs-code header="app.html" path="adev/src/content/examples/aria/select/src/disabled/retro/app/app.html"/> <docs-code header="app.css" path="adev/src/content/examples/aria/select/src/disabled/retro/app/app.css"/> </docs-code-multifile> </docs-tab> </docs-tab-group>When disabled, the select shows a disabled visual state and blocks all user interaction. Screen readers announce the disabled state to assistive technology users.
The select 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 a select 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 {MySelectComponent} from './my-select'; // Your component
describe('MySelectComponent', () => {
let fixture: ComponentFixture<MySelectComponent>;
let loader: HarnessLoader;
beforeEach(async () => {
TestBed.configureTestingModule({
imports: [MySelectComponent],
});
fixture = TestBed.createComponent(MySelectComponent);
await fixture.whenStable();
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should allow selecting an option', async () => {
// Load the combobox harness (which acts as the select trigger)
const select = await loader.getHarness(ComboboxHarness);
// Verify it is closed initially
expect(await select.isOpen()).toBe(false);
// Open the dropdown
await select.open();
expect(await select.isOpen()).toBe(true);
// Get the listbox harness from the popup
const listbox = await select.getPopupWidget(ListboxHarness);
const options = await listbox.getOptions();
expect(options.length).toBe(3);
// Click the second option
await options[1].click();
// Verify the dropdown closed and the value updated
expect(await select.isOpen()).toBe(false);
expect(await (await select.host()).text()).toContain('Option 2');
});
});
For detailed API documentation, inspect the following API references:
The select pattern integrates with CDK Overlay for smart positioning. Use cdkConnectedOverlay to handle viewport edges and scrolling automatically.