npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ngui/auto-complete

v22.0.0

Published

Angular Input Autocomplete

Readme

@ngui/auto-complete

CI npm version npm downloads npm license GitHub issues

A versatile Angular autocomplete library that works as both a directive (attached to any input) and a standalone component.

Live Demo


Installation

npm install @ngui/auto-complete @angular/cdk

The directive positions its dropdown with the CDK Overlay, so @angular/cdk is a peer dependency and your app must include the CDK overlay styles once:

/* styles.scss — skip this if you already import an Angular Material theme (it bundles them) */
@import '@angular/cdk/overlay-prebuilt.css';

Styling the dropdown: because the directive renders its dropdown in an overlay at the document root, any custom dropdown styles (e.g. classes used by a list-formatter or template) must be global, not scoped to an ancestor of the input. See Theming to restyle it with CSS variables.

Setup

Standalone (Angular 21+)

The component and directive are standalone. Import them directly into your standalone component (or NgModule) imports:

import { NguiAutoCompleteComponent, NguiAutoCompleteDirective } from '@ngui/auto-complete';

@Component({
  // ...
  imports: [FormsModule, NguiAutoCompleteComponent, NguiAutoCompleteDirective],
})
export class MyComponent {}

NgModule (Angular 20 and below)

NguiAutoCompleteModule was removed in v21 — import the standalone component/directive shown above instead. If your app still relies on the NgModule, install the matching major and import the module as before:

  • Angular 20npm install @ngui/auto-complete@20 (standalone, but NguiAutoCompleteModule is still re-exported for back-compat).
  • Angular 19 and oldernpm install @ngui/auto-complete@19.
import { NguiAutoCompleteModule } from '@ngui/auto-complete';

@NgModule({
  imports: [BrowserModule, FormsModule, NguiAutoCompleteModule],
})
export class AppModule {}

Usage

As a Directive

Attach to any element containing an input. The directive is a ControlValueAccessor, so it binds with [(ngModel)] like any form control:

<!-- Directly on an input -->
<input ngui-auto-complete [(ngModel)]="myValue" [source]="myArray" />

<!-- On a wrapping div: put the value binding on the host element -->
<div ngui-auto-complete [(ngModel)]="myValue" [source]="myArray">
  <input />
</div>

Reactive forms

Because the directive is a ControlValueAccessor, [formControl] and formControlName work directly:

<input ngui-auto-complete [formControl]="cityControl" [source]="cities" />

<form [formGroup]="form">
  <input ngui-auto-complete formControlName="city" [source]="cities" />
</form>

As a Component

Use <ngui-auto-complete> directly, control its visibility with @if:

<input [(ngModel)]="myValue" (focus)="show = true" (blur)="show = false" />
@if (show) {
  <ngui-auto-complete
    [source]="myArray"
    [show-input-tag]="false"
    [show-dropdown-on-init]="true"
    [(value)]="myValue">
  </ngui-auto-complete>
}

Remote / Observable Source

<input ngui-auto-complete
  [(ngModel)]="address"
  [source]="searchFn"
  path-to-data="results"
  list-formatter="formatted_address"
  min-chars="2" />
searchFn = (keyword: string): Observable<any> => {
  return this.http.get(`https://api.example.com/search?q=${keyword}`);
};

Custom dropdown templates

Pass Angular ng-templates for custom rendering: itemTemplate (each row — receives the item as $implicit and the row index as index), headerTemplate (a header row), and loadingTemplate (shown while remote data loads). They work on both the component and the directive:

<input ngui-auto-complete [(ngModel)]="myValue" [source]="myArray"
  [itemTemplate]="row" [headerTemplate]="head" />

<ng-template #head>Suggestions</ng-template>
<ng-template #row let-item let-i="index">
  <strong>{{ i + 1 }}.</strong> {{ item.name }} — <em>{{ item.country }}</em>
</ng-template>

API Reference

One reference for both surfaces. The Applies to column says whether each option works on the directive ([ngui-auto-complete]), the component (<ngui-auto-complete>), or both. Every option keeps its kebab-case attribute name; numeric/boolean inputs accept both the attribute form (min-chars="2") and the bound form ([min-chars]="2").

Value & forms

How the selected value is read and written.

| Option | Type | Default | Applies to | Description | |--------|------|---------|------------|-------------| | [(ngModel)] / [formControl] / formControlName | T | — | Directive | The directive is a ControlValueAccessor, so the value flows through Angular forms. (ngModelChange) / the control's valueChanges fire on every accepted value | | [(value)] | T | — | Component | Two-way bindable selected value on the standalone component | | select-value-of | string | — | Directive | Commit this property's value on selection instead of the whole object |

Data & filtering

Where suggestions come from and how the keyword is matched.

| Option | Type | Default | Applies to | Description | |--------|------|---------|------------|-------------| | source | T[] \| string \| ((keyword) => Observable<T[]>) | — | Both | Required (input.required — omitting [source] is a compile-time error). Local array, URL string, or a function returning an Observable | | path-to-data | string | — | Both | Dot-path to the array in an HTTP response, e.g. data.results | | min-chars | number | 0 | Both | Minimum characters before fetching/filtering | | max-num-list | number | unlimited | Both | Maximum number of suggestions to show | | match-formatted | boolean | false | Both | Match the keyword against formatted values instead of the raw data | | ignore-accents | boolean | true | Both | Treat accented characters as their base characters when matching |

Display & formatting

How rows and the selected value are rendered.

| Option | Type | Default | Applies to | Description | |--------|------|---------|------------|-------------| | display-with | string \| ((item) => string) | item's value | Directive | Text shown in the input after selecting an object — a property name (display-with="name") or a function ([display-with]="fn") | | list-formatter | string \| ((item) => string) | — | Both | Format each dropdown row. String pattern (key) name or a function | | itemTemplate | TemplateRef | — | Both | ng-template for each dropdown row (context: $implicit = item, index = row index). Takes precedence over list-formatter | | headerTemplate | TemplateRef | — | Both | ng-template for a non-selectable header row | | loadingTemplate | TemplateRef | — | Both | ng-template shown while remote data loads (falls back to loading-text) | | loading-text | string | 'Loading' | Both | Text shown while fetching remote data | | blank-option-text | string | — | Both | Adds an empty first option with this label | | no-match-found-text | string | — | Both | Text shown when nothing matches. Set to "" to suppress the row entirely | | placeholder | string | — | Component | Placeholder for the component's internal input | | auto-complete-placeholder | string | — | Directive | Placeholder for the dropdown's (normally hidden) internal input |

Behavior

Interaction and selection behavior.

| Option | Type | Default | Applies to | Description | |--------|------|---------|------------|-------------| | accept-user-input | boolean | true | Both | Allow values that are not in the list | | auto-select-first-item | boolean | false | Both | Pre-highlight the first suggestion | | select-on-blur | boolean | false | Both | Select the highlighted item on blur | | tab-to-select | boolean | true | Both | Select the highlighted item on the Tab key | | re-focus-after-select | boolean | true | Both | Return focus to the input after a selection | | autocomplete | boolean | false | Both | When false, sets the native autocomplete="off" on the input | | open-on-focus | boolean | true | Directive | Open the dropdown when the input gains focus | | close-on-focusout | boolean | true | Directive | Close the dropdown on focusout | | show-input-tag | boolean | true | Component | Render an <input> inside the component | | show-dropdown-on-init | boolean | false | Component | Open the dropdown as soon as the component appears |

Layout & positioning

| Option | Type | Default | Applies to | Description | |--------|------|---------|------------|-------------| | open-direction | 'auto' \| 'up' \| 'down' | 'auto' | Both | Preferred side. For the directive (CDK overlay) up/down set the preference and the overlay still flips when there isn't room; for the component, up renders above via CSS and auto/down keep it below | | z-index | number | 1 | Directive | z-index of the dropdown overlay. Rarely needed — the CDK overlay already renders above page content; only useful to order overlapping overlays |

RTL: there is no RTL input — the directive's overlay follows the input's computed direction, and the component's drop-up anchors via logical CSS (inset-inline-start). Just set dir="rtl" on the element or an ancestor (or the document direction).

Events

Both surfaces emit the same two outputs.

| Output | Payload | Applies to | Description | |--------|---------|------------|-------------| | (valueSelected) | NguiAutoCompleteSelection | Both | Fires when a value is committed. Use fromSource to tell a list pick from a typed value | | (noMatchFound) | void | Both | Fires when the filtered list is empty and the min-chars threshold is met — use it to show an "Add new…" affordance |

The (valueSelected) payload:

interface NguiAutoCompleteSelection<T = any> {
  value: T;          // the committed value (same as [(ngModel)] / [(value)])
  item: T;           // the full picked object (or the typed text)
  index: number;     // row in the shown list; -1 when typed (fromSource = false)
  fromSource: boolean; // true = picked from [source]; false = typed by the user
}

Type inference

NguiAutoCompleteComponent<T = any> is generic. Bind a typed [source] (a typed array or a function returning Observable<T[]>) and Angular infers the item type — [(value)], (valueSelected) (NguiAutoCompleteSelection<T>) and the itemTemplate context are then all typed with no extra annotation:

<ngui-auto-complete [source]="cities" [(value)]="city" (valueSelected)="onPick($event)"></ngui-auto-complete>
cities: City[] = [/* … */];
city?: City;
onPick(e: NguiAutoCompleteSelection<City>) { /* e.item is City */ }

It defaults to any, so existing templates are unaffected. The directive ([ngui-auto-complete]) stays loosely typed — Angular can't infer a generic for an attribute directive in templates, so its (valueSelected) payload is NguiAutoCompleteSelection<any>.


Theming

Restyle the dropdown by overriding these CSS variables. Each has a sensible default, so set only what you need. Set them on :root — the directive's dropdown renders in an overlay at the document root, so variables on an ancestor of the input won't reach it.

| Variable | Default | Controls | |----------|---------|----------| | --ngui-ac-background | #fff | Dropdown background | | --ngui-ac-color | inherit | Text color | | --ngui-ac-border | 1px solid rgba(0,0,0,.12) | Dropdown border | | --ngui-ac-border-radius | 4px | Corner radius | | --ngui-ac-shadow | 0 4px 12px rgba(0,0,0,.15) | Elevation shadow | | --ngui-ac-max-height | 256px | Height cap (none to remove) | | --ngui-ac-z-index | 10 | Stacking order of the floating list (standalone <ngui-auto-complete>; the directive's overlay uses the z-index input instead) | | --ngui-ac-item-padding | 6px 12px | Row padding (density) | | --ngui-ac-item-border | 1px solid rgba(0,0,0,.06) | Row divider | | --ngui-ac-hover-background | rgba(0,0,0,.06) | Row hover background | | --ngui-ac-selected-background | rgba(0,0,0,.1) | Highlighted row background |

/* e.g. a dark dropdown */
:root {
  --ngui-ac-background: #2b2b2b;
  --ngui-ac-color: #eee;
  --ngui-ac-item-border: 1px solid rgba(255, 255, 255, 0.08);
  --ngui-ac-hover-background: rgba(255, 255, 255, 0.08);
  --ngui-ac-selected-background: rgba(255, 255, 255, 0.16);
}

Angular Version Compatibility

This library follows Angular's versioning: @ngui/[email protected] supports Angular N. Install the version matching your Angular major (e.g. Angular 22 → npm install @ngui/auto-complete@22).


Development

Quick start

git clone https://github.com/ng2-ui/auto-complete.git
cd auto-complete
npm install

# Build library in watch mode, then in a second terminal start the demo app
npm run build-lib:watch
npm start

Available scripts

| Script | Description | |--------|-------------| | npm start | Serve the demo app on port 4200 | | npm test | Run unit tests (Karma/Jasmine) | | npm run lint | Lint all TypeScript and HTML | | npm run build-lib:watch | Build library in watch mode (for demo development) | | npm run build-lib:prod | Production library build | | npm run build-docs | Build demo app for GitHub Pages deployment | | npm run cypress:open | Open Cypress e2e test runner | | npm run cypress:run | Run Cypress e2e tests headlessly |

Publish a new version

# 1. Update version in projects/auto-complete/package.json
# 2. Build the library. This also copies README/CHANGELOG/MIGRATION/LICENSE
#    into dist/ for you (via the copy-lib script).
npm run build-lib:prod

# 3. Move into the built output — do NOT run npm publish from the project root
#    (the root package.json is private and will fail)
cd dist
npm publish --access public

Contributing — help wanted!

This library is maintained by a small team with limited time — every contribution genuinely helps keep it alive and improving. If you use it and find it useful, here are easy ways to give back:

  • Found a bug? Open an issue with a clear description and a minimal reproduction
  • Have an idea? Check the open issues first, then open a new one if needed
  • Want to fix something? Pull requests are always welcome — small focused PRs are easiest to review
  • Using it at work? A GitHub star goes a long way for visibility

Issues and pull requests: github.com/ng2-ui/auto-complete.

Changelog

See CHANGELOG.md for the full history of changes.

License

MIT