Primitives
A select is a form control that allows users to select options from a list.
Import the Select primitives from ng-primitives/select.
import {
NgpSelect,
NgpSelectDropdown,
NgpSelectPortal,
NgpSelectOption,
NgpSelectInput,
NgpSelectList,
} from 'ng-primitives/select';
Assemble the select directives in your template.
<div ngpSelect>
<div *ngpSelectPortal ngpSelectDropdown>
<div ngpSelectOptionValue="option-1" ngpSelectOption>One</div>
<div ngpSelectOptionValue="option-2" ngpSelectOption>Two</div>
<div ngpSelectOptionValue="option-3" ngpSelectOption>Three</div>
</div>
</div>
Create a reusable component that uses the NgpSelect directive.
Generate a reusable select component using the Angular CLI.
ng g ng-primitives:primitive select
path: The path at which to create the component file.prefix: The prefix to apply to the generated component selector.component-suffix: The suffix to apply to the generated component class name.file-suffix: The suffix to apply to the generated component file name. Defaults to component.styles: How component styles should be generated. css (default) includes the full example styles; unstyled omits them entirely so you can style the component yourself.example-styles (deprecated): still supported for compatibility - true maps to styles: css, false maps to styles: unstyled.You can customize the offset using either a simple number or an object for more precise control:
<!-- Simple number offset -->
<div ngpSelect [ngpSelectDropdownOffset]="12">Dropdown with 12px offset</div>
<!-- Object offset for precise control -->
<div ngpSelect [ngpSelectDropdownOffset]="{mainAxis: 8, crossAxis: 4, alignmentAxis: 2}">
Dropdown with custom offset
</div>
The select can be used within a form field for better integration with form controls.
The native select is a simple wrapper around the native select element.
The select automatically integrates with the form field primitives.
The select component can be rendered inside a custom container. You can open DevTools and inspect the DOM to see it mounted within this container.
When dealing with large datasets (thousands of items), you can use TanStack Virtual or other virtualization libraries to efficiently render only the visible options, improving performance:
Options without a value do not perform any selection by default. You can use this to implement custom behavior, such as clearing the selection. These options are still included in keyboard navigation.
Add ngpSelectInput inside the dropdown to provide a search field. Filtering is left to the consumer. Wrap the options in ngpSelectList to keep the accessibility tree valid.
The following directives are available to import from the ng-primitives/select package:
You can configure the default options for all selects in your application by using the provideSelectConfig function in a providers array.
import { provideSelectConfig } from 'ng-primitives/select';
bootstrapApplication(AppComponent, {
providers: [
provideSelectConfig({
placement: 'bottom',
container: document.body,
flip: true,
offset: 4,
}),
],
});
The select primitive follows the WAI-ARIA Combobox pattern. The trigger uses role="combobox" with aria-expanded and aria-controls. The dropdown uses role="listbox" (with aria-multiselectable reflecting ngpSelectMultiple) and options use role="option" with aria-selected. Focus is managed using aria-activedescendant.
When a search input (ngpSelectInput) is used, the combobox semantics move to the input, which receives focus when the dropdown opens. The dropdown becomes a dialog wrapping the input and an ngpSelectList (role="listbox"), and the input drives the options via aria-activedescendant and aria-controls. Naming is left to the consumer, so add an aria-label (or aria-labelledby) to both the dropdown dialog and the list.
When a search input (ngpSelectInput) has focus, Home and End keep their text editing behaviour and move the caret within the search term. Space types a space rather than toggling the dropdown.
Copyright © 2026 Angular Primitives
This site is powered by Netlify