@kit-ng-ui/autocomplete
v0.1.0
Published
Kit UI AutoComplete component — ant-design feature parity.
Readme
@kit-ng-ui/autocomplete
A free-text input with a suggestion overlay. Mirrors ant-design's AutoComplete.
Unlike <kit-select>, the bound value is the raw text the user typed — suggestions are hints, not the source of truth. Picking a suggestion writes its value into the input.
Install
pnpm add @kit-ng-ui/autocomplete @kit-ng-ui/core @kit-ng-ui/iconsStyles
@use '@kit-ng-ui/core/styles' as *;
@use '@kit-ng-ui/autocomplete/styles' as autocomplete;Use
import { Component, signal } from '@angular/core';
import { KitAutocompleteComponent, type KitAutocompleteOption } from '@kit-ng-ui/autocomplete';
@Component({
standalone: true,
imports: [KitAutocompleteComponent],
template: `
<kit-autocomplete
[options]="suggestions"
[(value)]="query"
placeholder="Search…"
[allowClear]="true"
/>
`,
})
export class AutocompleteDemo {
query = signal('');
suggestions: KitAutocompleteOption[] = [
{ value: 'apple' },
{ value: 'apricot' },
{ value: 'banana' },
];
}Server-driven suggestions
Set searchMode="server" to flip the component into query-driven mode: the built-in client filter is bypassed and focus alone no longer opens the dropdown — typing does. Push fresh [options] from (search):
<kit-autocomplete
[options]="hits()"
searchMode="server"
(search)="onSearch($event)"
placeholder="Type to search…"
/>Debounce on the host.
(search)fires on every keystroke — Kit UI does not throttle. Wrap your handler withdebounceTime(RxJS) or a signal-debounce helper before calling the server, otherwise a fast typist spawns one request per character.
API
| Input | Type | Default |
| --------------------------- | ------------------------------------------------- | ----------- |
| options | KitAutocompleteOption[] | [] |
| value | string | '' |
| placeholder | string \| null | null |
| size | 'sm' \| 'md' \| 'lg' | 'md' |
| status | 'default' \| 'error' \| 'warning' | 'default' |
| disabled | boolean | false |
| readOnly | boolean | false |
| allowClear | boolean | false |
| block | boolean — fill parent width | false |
| backfill | boolean — write highlighted option into input on arrow nav | false |
| defaultActiveFirstOption | boolean | true |
| searchMode | 'local' \| 'server' — 'server' skips built-in filter and keeps the dropdown closed on focus until typing | 'local' |
| filterOption | boolean — false to skip client filtering (ignored in server mode) | true |
| notFoundContent | string \| null | null |
| maxLength | number \| null | null |
Outputs: (valueChange), (search), (optionSelect), (openChange), (clear).
Implements ControlValueAccessor — works with [(ngModel)] and reactive FormControl.
KitAutocompleteOption
interface KitAutocompleteOption {
readonly value: string;
readonly label?: string; // defaults to `value`
readonly disabled?: boolean;
}Keyboard
| Key | Action |
| ----------- | ----------------------------------------------- |
| ArrowDown | Open dropdown / move highlight down |
| ArrowUp | Move highlight up |
| Enter | Pick highlighted option |
| Escape | Close dropdown (restore typed text if backfill) |
| Tab | Close dropdown, advance focus |
Behavior notes
- The bound value is always the typed string. Picking an option writes
option.valueinto the input — there is no separate "selected option" model. - Default client-side filter is case-insensitive substring match on
label ?? value. Disable with[filterOption]="false"(or switch tosearchMode="server") and supply your own option list. - In
searchMode="server", focusing an empty input does not open the dropdown — the host is the only thing that can populate suggestions, so we wait for a real query before showing anything. - The dropdown closes on outside click and on
focusoutwhen focus leaves the host. notFoundContentis treated as a string slot:nullor empty string hides the empty-state panel entirely. Pass a non-empty string to show one.- With
[backfill]="true", ArrowDown/ArrowUp writes the highlighted suggestion into the visible input as a preview only —(valueChange)and the form model are not updated until you commit with Enter or click. Escape restores what you typed.
Forms binding precedence
[value] and form directives ([formControl] / [(ngModel)]) write the same model from different sides. Do not bind both on the same instance — last-write-wins behavior is subtle and easy to misread when debugging. Pick one:
- Reactive / template-driven forms → use the form directive only; omit
[value]. - Local state outside a form → bind
[value]+(valueChange)(or[(value)]against a plain field).
Not yet implemented (TODO parity): custom option templates, option groups, dropdownRender, virtual scrolling, async loading state, prefix/suffix slots inside the input.
