Autocomplete
Suggest destinations while the user types, with strict selection or free text.
- Category
- Forms and selection
- Import
@neural-ui/core/autocomplete- Selector
neu-autocomplete
import { NeuAutocompleteComponent } from '@neural-ui/core/autocomplete';Usage
Signal Forms
Value: โ ยท Valid: false
Try and configure
nullStructured data, callbacks and templates are shown in the examples and API.
Code adds advanced options when they differ from the default. Current configuration data and values appear in the template state.
Generated template: reflects the settings above. Imports and state are in the Code tab.
<neu-autocomplete
[options]="destinations"
[suggestions]="suggestions()"
(queryChange)="query.set($event)"
(suggestionsRequest)="refreshSuggestions($event.query)"
[(value)]="destination"
[dropdown]="true"
[clearAriaLabel]="'Clear selection'"
[delay]="0"
[dropdownAriaLabel]="'Show destinations'"
[emptyLabel]="'No matches'"
[floatingLabel]="true"
[fluid]="true"
[label]="'Destination'"
[listAriaLabel]="'Destination'"
[loadingLabel]="'Loading destinations'"
[placeholder]="'Choose a destination'"
/>These values match the current preview. Complete handlers, Core imports and templates are in Source.
import { signal } from '@angular/core';
export const destinations = [
{
"value": "madrid",
"label": "Madrid"
},
{
"value": "lisbon",
"label": "Lisbon"
},
{
"value": "paris",
"label": "Paris"
},
{
"value": "rome",
"label": "Rome",
"disabled": true
}
];
export const suggestions = signal([
{
"value": "madrid",
"label": "Madrid"
},
{
"value": "lisbon",
"label": "Lisbon"
},
{
"value": "paris",
"label": "Paris"
},
{
"value": "rome",
"label": "Rome",
"disabled": true
}
]);
export const destination = signal(null);These inputs require a model or function, not a checkbox. Edit the same-named field in the Source component and bind it in the template; data already used by this preview appears in the state above.
compareWith ยท (left: V, right: V) => booleanIn Source: define compareWith with this type and use [compareWith]="compareWith" (or compareWith() for a signal).
errors ยท readonly ValidationError.WithOptionalFieldTree[]In Source: define errors with this type and use [errors]="errors" (or errors() for a signal).
filterConfig ยท Readonly<NeuOptionFilterConfig<T>>In Source: define filterConfig with this type and use [filterConfig]="filterConfig" (or filterConfig() for a signal).
groupConfig ยท NeuOptionGroupConfig<T, G> | nullIn Source: define groupConfig with this type and use [groupConfig]="groupConfig" (or groupConfig() for a signal).
groups ยท readonly G[]In Source: define groups with this type and use [groups]="groups" (or groups() for a signal).
groupSuggestions ยท readonly G[] | nullIn Source: define groupSuggestions with this type and use [groupSuggestions]="groupSuggestions" (or groupSuggestions() for a signal).
optionDisabled ยท NeuOptionDisabledAccessor<T> | nullIn Source: define optionDisabled with this type and use [optionDisabled]="optionDisabled" (or optionDisabled() for a signal).
optionLabel ยท NeuOptionLabelAccessor<T> | nullIn Source: define optionLabel with this type and use [optionLabel]="optionLabel" (or optionLabel() for a signal).
options ยท readonly T[]In Source: define options with this type and use [options]="options" (or options() for a signal).
optionValue ยท NeuOptionValueAccessor<T, V> | nullIn Source: define optionValue with this type and use [optionValue]="optionValue" (or optionValue() for a signal).
pattern ยท readonly RegExp[]In Source: define pattern with this type and use [pattern]="pattern" (or pattern() for a signal).
value ยท NeuAutocompleteValue<V, F>In Source: define value with this type and use [value]="value" (or value() for a signal).
Value and events
Accessibility and keyboard
Key | Action |
|---|---|
| Tab | Moves focus into or out of the control. |
| ArrowDown / ArrowUp | Moves the active option through available options. |
| Enter | Activates the focused option. |
| Escape | Closes the panel without selecting another option. |
API
Inputs
Configure the component with [property]="value". Your application supplies these values; the component does not replace the state you pass in.
Name | Type | Default | Template binding | Description |
|---|---|---|---|---|
ariaDescribedBy | string | null | null | [ariaDescribedBy] | |
ariaLabel | string | null | null | [ariaLabel] | |
ariaLabelledBy | string | null | null | [ariaLabelledBy] | |
autocomplete | string | 'off' | [autocomplete] | |
autofocus | boolean | false | [autofocus] | |
autoHighlight | boolean | false | [autoHighlight] | |
autoOptionFocus | boolean | false | [autoOptionFocus] | |
clearable | boolean | true | [clearable] | |
clearAriaLabel | string | 'Clear value' | [clearAriaLabel] | |
compareWith | (left: V, right: V) => boolean | Object.isDerived default | [compareWith] | |
completeOnFocus | boolean | false | [completeOnFocus] | |
dataFirst | number | 0 | [dataFirst] | |
delay | number | 300 | [delay] | |
dirty | boolean | false | [dirty] | |
disabled | boolean | false | [disabled] | |
dropdown | boolean | false | [dropdown] | |
dropdownAriaLabel | string | 'Show suggestions' | [dropdownAriaLabel] | |
dropdownMode | NeuAutocompleteDropdownMode | 'blank' | [dropdownMode] | |
emptyLabel | string | 'No results' | [emptyLabel] | |
emptySelectionMessage | string | 'No selected item' | [emptySelectionMessage] | |
errorMessage | string | '' | [errorMessage] | |
errors | readonly ValidationError.WithOptionalFieldTree[] | [] | [errors] | |
filterConfig | Readonly<NeuOptionFilterConfig<T>> | {} | [filterConfig] | |
floatingLabel | boolean | false | [floatingLabel] | |
fluid | boolean | false | [fluid] | |
focusOnHover | boolean | true | [focusOnHover] | |
groupConfig | NeuOptionGroupConfig<T, G> | null | null | [groupConfig] | |
groups | readonly G[] | [] | [groups] | |
groupSuggestions | readonly G[] | null | null | [groupSuggestions] | |
hidden | boolean | false | [hidden] | |
hint | string | '' | [hint] | |
id | string | null | null | [id] | |
inputId | string | null | null | [inputId] | |
inputSize | number | null | null | [inputSize] | |
invalid | boolean | false | [invalid] | |
label | string | '' | [label] | |
lazy | boolean | false | [lazy] | |
listAriaLabel | string | 'Suggestions' | [listAriaLabel] | |
loading | boolean | false | [loading] | |
loadingLabel | string | 'Loading...' | [loadingLabel] | |
maxLength | number | undefined | undefined | [maxLength] | |
minLength | number | undefined | undefined | [minLength] | |
minQueryLength | number | 0 | [minQueryLength] | |
mode | F | 'strict' as FDerived default | [mode] | |
name | string | '' | [name] | |
optionDisabled | NeuOptionDisabledAccessor<T> | null | null | [optionDisabled] | |
optionLabel | NeuOptionLabelAccessor<T> | null | null | [optionLabel] | |
options | readonly T[] | [] | [options] | |
optionValue | NeuOptionValueAccessor<T, V> | null | null | [optionValue] | |
pattern | readonly RegExp[] | [] | [pattern] | |
pending | boolean | false | [pending] | |
placeholder | string | '' | [placeholder] | |
readonly | boolean | false | [readonly] | |
required | boolean | false | [required] | |
scrollHeight | string | '240px' | [scrollHeight] | |
searchMessage | string | null | null | [searchMessage] | |
selectionMessage | string | '{0} item selected' | [selectionMessage] | |
selectOnFocus | boolean | false | [selectOnFocus] | |
showEmptyMessage | boolean | true | [showEmptyMessage] | |
size | NeuAutocompleteSize | 'md' | [size] | |
suggestions | readonly T[] | null | null | [suggestions] | |
tabindex | number | 0 | [tabindex] | |
totalItems | number | null | null | [totalItems] | |
touched | boolean | false | [touched] | |
type | string | 'text' | [type] | |
variant | NeuAutocompleteVariant | 'outline' | [variant] | |
virtualScroll | boolean | false | [virtualScroll] | |
virtualScrollBuffer | number | 3 | [virtualScrollBuffer] | |
virtualScrollItemSize | number | null | null | [virtualScrollItemSize] | |
virtualScrollVisibleItems | number | 8 | [virtualScrollVisibleItems] |
Models
A model supports [(property)]="signal" or the [property] and (propertyChange) pair. Choose one form, not both.
Name | Type | Default | Template binding | Description |
|---|---|---|---|---|
value | NeuAutocompleteValue<V, F> | null as NeuAutocompleteValue<V, F>Derived default | [(value)] |
Outputs
Listen to an event with (event)="handler($event)". The table explains the data your handler receives and how to use it.
Name | Payload | Template binding | Description |
|---|---|---|---|
cleared | NeuAutocompleteClearEvent<V, F> | (cleared)="onCleared($event)" | |
closed | void | (closed)="onClosed($event)" | |
dropdownClick | NeuAutocompleteDropdownClickEvent | (dropdownClick)="onDropdownClick($event)" | |
focusEntered | FocusEvent | (focusEntered)="onFocusEntered($event)" | |
focusLeft | FocusEvent | (focusLeft)="onFocusLeft($event)" | |
inputKeydown | KeyboardEvent | (inputKeydown)="onInputKeydown($event)" | |
keyUp | KeyboardEvent | (keyUp)="onKeyUp($event)" | |
opened | void | (opened)="onOpened($event)" | |
optionActivated | NeuOptionActivatedEvent<T, V> | (optionActivated)="onOptionActivated($event)" | |
queryChange | string | (queryChange)="onQueryChange($event)" | |
suggestionsRequest | NeuAutocompleteSuggestionsRequest | (suggestionsRequest)="onSuggestionsRequest($event)" | |
touch | void | (touch)="onTouch($event)" |
Templates
ng-content projects content into the component. TemplateRef inputs receive a template; ng-template directives identify templates with a typed context. A directive shared by an entrypoint is not necessarily a slot of this component.
Name | Mechanism | Contract |
|---|---|---|
NeuAutocompleteClearIconDirectiveView example | Public template directive (entrypoint) | ng-template[neuAutocompleteClearIcon]template.d.ts context.d.ts |
NeuAutocompleteDropdownIconDirectiveView example | Public template directive (entrypoint) | ng-template[neuAutocompleteDropdownIcon]template.d.ts context.d.ts |
NeuAutocompleteEmptyDirectiveView example | Public template directive (entrypoint) | ng-template[neuAutocompleteEmpty]template.d.ts context.d.ts |
NeuAutocompleteFooterDirectiveView example | Public template directive (entrypoint) | ng-template[neuAutocompleteFooter]template.d.ts context.d.ts |
NeuAutocompleteGroupDirectiveView example | Public template directive (entrypoint) | ng-template[neuAutocompleteGroup]template.d.ts context.d.ts |
NeuAutocompleteHeaderDirectiveView example | Public template directive (entrypoint) | ng-template[neuAutocompleteHeader]template.d.ts context.d.ts |
NeuAutocompleteItemDirectiveView example | Public template directive (entrypoint) | ng-template[neuAutocompleteItem]template.d.ts context.d.ts |
NeuAutocompleteLoaderDirectiveView example | Public template directive (entrypoint) | ng-template[neuAutocompleteLoader]template.d.ts context.d.ts |
NeuAutocompleteLoadingIconDirectiveView example | Public template directive (entrypoint) | ng-template[neuAutocompleteLoadingIcon]template.d.ts context.d.ts |
Each example demonstrates a different template. Switch between Demo and Code to inspect its implementation, imports and state.
ClearIcon template
NeuAutocompleteClearIconDirective
Use the dropdown button or type to open the suggestions.
DropdownIcon template
NeuAutocompleteDropdownIconDirective
Use the dropdown button or type to open the suggestions.
Empty template
NeuAutocompleteEmptyDirective
Open the control to see the empty state.
Footer template
NeuAutocompleteFooterDirective
Use the dropdown button or type to open the suggestions.
Group template
NeuAutocompleteGroupDirective
Use the dropdown button or type to open the suggestions.
Header template
NeuAutocompleteHeaderDirective
Use the dropdown button or type to open the suggestions.
Item template
NeuAutocompleteItemDirective
Use the dropdown button or type to open the suggestions.
Loader template
NeuAutocompleteLoaderDirective
Use the dropdown button or type to open the suggestions.
LoadingIcon template
NeuAutocompleteLoadingIconDirective
Use the dropdown button or type to open the suggestions.
Public methods
Name | Contract |
|---|---|
clear | clear(originalEvent?: Event | null, reason?: 'button' | 'force-selection' | 'programmatic'): void; |
close | close(originalEvent?: Event | null, reason?: OverlayReason, restoreFocus?: boolean): void; |
focus | focus(): void; |
open | open(originalEvent?: Event | null, reason?: OverlayReason): void; |
openAll | openAll(event?: Event | null): void; |
reset | reset(): void; |
selectOption | selectOption(option: T, originalEvent?: Event | null): void; |
Public Types
Open a type to inspect its definition and interface fields.
import type { NeuAutocompleteMode } from '@neural-ui/core/autocomplete';
import type { NeuAutocompleteValue } from '@neural-ui/core/autocomplete';
import type { NeuAutocompleteClearEvent } from '@neural-ui/core/autocomplete';
// Public declaration (reference only)
export interface NeuAutocompleteClearEvent<V, F extends NeuAutocompleteMode = 'strict'> {
readonly originalEvent: Event | null;
readonly previousText: string;
readonly previousValue: NeuAutocompleteValue<V, F>;
readonly reason: 'button' | 'input' | 'force-selection' | 'programmatic';
}import type { NeuAutocompleteCompletionSource } from '@neural-ui/core/autocomplete';
import type { NeuAutocompleteCompleteEvent } from '@neural-ui/core/autocomplete';
// Public declaration (reference only)
export interface NeuAutocompleteCompleteEvent {
readonly originalEvent: Event | null;
readonly query: string;
readonly requestId: number;
readonly source: NeuAutocompleteCompletionSource;
}import type { NeuAutocompleteCompletionSource } from '@neural-ui/core/autocomplete';
// Public declaration (reference only)
export type NeuAutocompleteCompletionSource = 'input' | 'focus' | 'dropdown' | 'programmatic';import type { NeuAutocompleteDropdownMode } from '@neural-ui/core/autocomplete';
import type { NeuAutocompleteDropdownClickEvent } from '@neural-ui/core/autocomplete';
// Public declaration (reference only)
export interface NeuAutocompleteDropdownClickEvent {
readonly mode: NeuAutocompleteDropdownMode;
readonly originalEvent: Event;
readonly query: string;
}import type { NeuAutocompleteDropdownMode } from '@neural-ui/core/autocomplete';
// Public declaration (reference only)
export type NeuAutocompleteDropdownMode = 'blank' | 'current';import type { NeuOptionGroupTemplateContext } from '@neural-ui/core/option-api';
import type { NeuAutocompleteGroupContext } from '@neural-ui/core/autocomplete';
// Public declaration (reference only)
export type NeuAutocompleteGroupContext<G> = NeuOptionGroupTemplateContext<G>;import type { NeuAutocompleteIconContext } from '@neural-ui/core/autocomplete';
// Public declaration (reference only)
export interface NeuAutocompleteIconContext {
readonly $implicit: boolean;
readonly active: boolean;
}import type { NeuOptionTemplateContext } from '@neural-ui/core/option-api';
import type { NeuAutocompleteItemContext } from '@neural-ui/core/autocomplete';
// Public declaration (reference only)
export interface NeuAutocompleteItemContext<T, V = unknown> extends NeuOptionTemplateContext<T> {
readonly label: string;
readonly value: V;
}import type { NeuOptionLoaderTemplateContext } from '@neural-ui/core/option-api';
import type { NeuAutocompleteLoaderContext } from '@neural-ui/core/autocomplete';
// Public declaration (reference only)
export type NeuAutocompleteLoaderContext = NeuOptionLoaderTemplateContext;import type { NeuAutocompleteMode } from '@neural-ui/core/autocomplete';
// Public declaration (reference only)
export type NeuAutocompleteMode = 'strict' | 'free-text';import type { NeuAutocompleteOption } from '@neural-ui/core/autocomplete';
// Public declaration (reference only)
export interface NeuAutocompleteOption<V = unknown> {
readonly disabled?: boolean;
readonly label: string;
readonly value: V;
}import type { NeuAutocompleteOverlayEvent } from '@neural-ui/core/autocomplete';
// Public declaration (reference only)
export interface NeuAutocompleteOverlayEvent {
readonly originalEvent: Event | null;
readonly reason: 'completion' | 'focus' | 'dropdown' | 'keyboard' | 'selection' | 'clear' | 'escape' | 'outside' | 'tab' | 'programmatic';
}import type { NeuAutocompleteSelectEvent } from '@neural-ui/core/autocomplete';
// Public declaration (reference only)
export interface NeuAutocompleteSelectEvent<T, V> {
readonly option: T;
readonly originalEvent: Event | null;
readonly value: V;
}import type { NeuAutocompleteSize } from '@neural-ui/core/autocomplete';
// Public declaration (reference only)
export type NeuAutocompleteSize = 'sm' | 'md' | 'lg';import type { NeuAutocompleteCompletionSource } from '@neural-ui/core/autocomplete';
import type { NeuViewportRange } from '@neural-ui/core/option-api';
import type { NeuAutocompleteSuggestionsRequest } from '@neural-ui/core/autocomplete';
// Public declaration (reference only)
export interface NeuAutocompleteSuggestionsRequest {
readonly query: string;
readonly queryRevision: number;
readonly range?: NeuViewportRange;
readonly reason: 'initial' | 'query' | 'viewport' | 'retry';
readonly requestId: number;
readonly source: NeuAutocompleteCompletionSource;
}import type { NeuAutocompleteMode } from '@neural-ui/core/autocomplete';
import type { NeuAutocompleteValue } from '@neural-ui/core/autocomplete';
// Public declaration (reference only)
export type NeuAutocompleteValue<V, F extends NeuAutocompleteMode = 'strict'> = F extends 'free-text' ? V | string | null : V | null;import type { NeuAutocompleteVariant } from '@neural-ui/core/autocomplete';
// Public declaration (reference only)
export type NeuAutocompleteVariant = 'outline' | 'solid';import type { NeuIndexRange } from '@neural-ui/core/option-api';
// Public declaration (reference only)
export interface NeuIndexRange {
readonly end: number;
readonly start: number;
}import type { NeuOptionPath } from '@neural-ui/core/option-api';
import type { NeuOptionAccessor } from '@neural-ui/core/option-api';
// Public declaration (reference only)
export type NeuOptionAccessor<T, R = unknown> = Exclude<keyof T, string> | NeuOptionPath<T> | ((option: T) => R);import type { NeuOptionActivatedEvent } from '@neural-ui/core/option-api';
// Public declaration (reference only)
export interface NeuOptionActivatedEvent<T, V> {
readonly option: T;
readonly originalEvent?: Event;
readonly source: 'pointer' | 'keyboard';
readonly value: V;
}import type { NeuOptionAccessor } from '@neural-ui/core/option-api';
import type { NeuOptionDisabledAccessor } from '@neural-ui/core/option-api';
// Public declaration (reference only)
export type NeuOptionDisabledAccessor<T> = NeuOptionAccessor<T, boolean>;import type { NeuOptionAccessor } from '@neural-ui/core/option-api';
import type { NeuOptionFilterMatchMode } from '@neural-ui/core/option-api';
import type { NeuOptionFilterStrategy } from '@neural-ui/core/option-api';
import type { NeuOptionFilterConfig } from '@neural-ui/core/option-api';
// Public declaration (reference only)
export interface NeuOptionFilterConfig<T> {
readonly fields?: readonly NeuOptionAccessor<T, unknown>[];
readonly locale?: string;
readonly matchMode?: NeuOptionFilterMatchMode;
readonly strategy?: NeuOptionFilterStrategy;
}import type { NeuOptionFilterMatchMode } from '@neural-ui/core/option-api';
// Public declaration (reference only)
export type NeuOptionFilterMatchMode = 'startsWith' | 'contains' | 'notContains' | 'endsWith' | 'equals' | 'notEquals';import type { NeuOptionFilterStrategy } from '@neural-ui/core/option-api';
// Public declaration (reference only)
export type NeuOptionFilterStrategy = 'client' | 'server';import type { NeuOptionAccessor } from '@neural-ui/core/option-api';
import type { NeuOptionGroupConfig } from '@neural-ui/core/option-api';
// Public declaration (reference only)
export interface NeuOptionGroupConfig<T, G> {
readonly childrenAccessor: NeuOptionAccessor<G, readonly T[]>;
readonly disabledAccessor?: NeuOptionAccessor<G, boolean> | null;
readonly labelAccessor: NeuOptionAccessor<G, unknown>;
}import type { NeuOptionGroupTemplateContext } from '@neural-ui/core/option-api';
// Public declaration (reference only)
export interface NeuOptionGroupTemplateContext<G> {
readonly $implicit: G;
readonly disabled: boolean;
readonly group: G;
readonly index: number;
readonly label: string;
}import type { NeuOptionAccessor } from '@neural-ui/core/option-api';
import type { NeuOptionLabelAccessor } from '@neural-ui/core/option-api';
// Public declaration (reference only)
export type NeuOptionLabelAccessor<T> = NeuOptionAccessor<T, string>;import type { NeuOptionLoaderTemplateContext } from '@neural-ui/core/option-api';
// Public declaration (reference only)
export interface NeuOptionLoaderTemplateContext {
readonly $implicit: number;
readonly count: number;
readonly end: number;
readonly first: number;
readonly logicalIndex: number;
}import type { NeuOptionPath } from '@neural-ui/core/option-api';
// Public declaration (reference only)
export type NeuOptionPath<T> = Extract<keyof T, string> | `${Extract<keyof T, string>}.${string}`;import type { NeuOptionTemplateContext } from '@neural-ui/core/option-api';
// Public declaration (reference only)
export interface NeuOptionTemplateContext<T> {
readonly $implicit: T;
readonly active: boolean;
readonly disabled: boolean;
readonly index: number;
readonly logicalIndex: number;
readonly option: T;
readonly selected: boolean;
}import type { NeuOptionAccessor } from '@neural-ui/core/option-api';
import type { NeuOptionValueAccessor } from '@neural-ui/core/option-api';
// Public declaration (reference only)
export type NeuOptionValueAccessor<T, V> = NeuOptionAccessor<T, V>;import type { NeuIndexRange } from '@neural-ui/core/option-api';
import type { NeuViewportRange } from '@neural-ui/core/option-api';
// Public declaration (reference only)
export interface NeuViewportRange {
readonly render: NeuIndexRange;
readonly visible: NeuIndexRange;
}Styles and tokens
Specific tokens
Token | Purpose | State / variant | Default / source | Fallback |
|---|---|---|---|---|
--neu-autocomplete-option-height | Inherited theme value used by this component | Field surface | 40pxRoot declaration | No token alias |
Shared tokens used
Override these on a local wrapper to affect this example. An override on :root affects other components that use the same token.
Token | Purpose here | Other impact | Default / fallback |
|---|---|---|---|
--neu-border | Normal control and cell borders | Shared by other Core consumers; scope the override. | rgba(15, 23, 42, 0.08) |
--neu-border-hover | Control borders on hover | Shared by other Core consumers; scope the override. | rgba(15, 23, 42, 0.16) |
--neu-error | Invalid field or danger-action color | Shared by other Core consumers; scope the override. | #dc2626 |
--neu-focus-ring | Normal keyboard-focus ring | Shared by other Core consumers; scope the override. | 0 0 0 var(--neu-focus-ring-width) rgba(0, 122, 255, 0.15) |
--neu-primary | Brand color for active controls and emphasis | Shared by other Core consumers; scope the override. | #007aff |
--neu-primary-50 | Subtle brand surface for hover and focus states | Shared by other Core consumers; scope the override. | #eff6ff |
--neu-primary-dark | Dark brand shade; outline and ghost Button text in the light theme | Shared by other Core consumers; scope the override. | #005fcc |
--neu-radius | Control corner radius | Shared by other Core consumers; scope the override. | 8px |