Releases: ng2-ui/auto-complete
Releases · ng2-ui/auto-complete
Release list
Angular 22 & Zoneless
[22.0.0] — 2026-06-07
A framework-only major: the public API is unchanged from 21.x. The consumer-visible changes are the
bumped Angular peer requirement and one dropdown-positioning fix (below).
⚠️ BREAKING CHANGES
- Requires Angular 22.
peerDependenciesnow require@angular/cdk,@angular/commonand
@angular/core^22.0.0. Angular 21 and older projects must stay on@ngui/auto-complete@21(or the
matching major).
Fixed
- Standalone
<ngui-auto-complete>dropdown now overlays the content below it instead of pushing it
down. When opening downward (the default), the list was rendered in normal document flow, so it grew
its host and could scroll the page; it now floats (position: absolute; top: 100%), matching the
existing upward (dropup) behavior. The directive's CDK-overlay path is unchanged. The float layer uses
z-index: var(--ngui-ac-z-index, 10), so you can override--ngui-ac-z-indexif it collides with other
stacked UI.
Internal (development tooling only — no impact on consumers)
ng updateto Angular 22:@angular/cli+@angular/build22.0.0,@angular/cdk+@angular/material
22.0.0,ng-packagr22.0.0,angular-eslint22.0.0, TypeScript 6.0.x.- Adopted
ChangeDetectionStrategy.OnPushin the demo app and the spec test-host components, satisfying
angular-eslint 22's new recommendedprefer-on-push-component-change-detectionrule with no opt-outs
(the published library component was alreadyOnPush). - TypeScript 6.0 config. TS 6 deprecates
baseUrl, so the roottsconfig.jsondrops it and uses
relativepathsinstead. - Enabled TypeScript
strictmode (strict: true) and tightened types accordingly — replacing
remaininganys with precise types (e.g.ReturnType<typeof setTimeout>, generics,unknown) and
adding null-safety guards. No public API or runtime behavior change (#500). - Enabled strict template type-checking (
strictTemplates: truein the rootangularCompilerOptions),
the natural companion tostrictabove. The library compiles cleanly under it; the only fix needed was a
more precise type on a demo field (open-directionbinding). No public API or runtime behavior change —
this only tightens the library's own build (#503). - Went fully zoneless. Angular 22 is zoneless by default, so
zone.jsis removed entirely: the demo app
bootstraps withprovideZonelessChangeDetection()(zone.jspolyfill dropped fromangular.json), the
unit-test harness dropszone.js/testingand configuresprovideZonelessChangeDetection()inTestBed,
andzone.jsis removed from dependencies. The published library was already zoneless-ready (signals +
OnPush, never shippedzone.js), so this is purely a demo/test change with no consumer impact. The few
fakeAsync/waitForAsyncspecs (which still requirezone.js) were rewritten to plainasync/await. - Bumped
jasmine-coreto 6.3.x (dev/test only). - Migrated the build to the
@angular/buildbuilders.angular.jsonnow uses@angular/build:*
(application,dev-server,ng-packagr,karma,extract-i18n) instead of the deprecated
@angular-devkit/build-angular:*aliases, and thekarma.conf.jsfiles drop the old framework/plugin
(the new karma builder wires these in itself). Removing the@angular-devkit/build-angularpackage
(replaced by@angular/build) drops the legacy Webpack toolchain — ~370 fewer installed packages and 0
audit vulnerabilities. Build output is unchanged. - Fixed the Cypress e2e config for TypeScript 6:
projects/demo/cypress/tsconfig.jsonnow sets an explicit
rootDir, which TS 6 requires (TS5011) when anoutDiris inherited and the included files span more
than one directory. Without it,npm run cypress:runfailed to compile the spec. Dev/test only.
What's Changed
- refactor: enable TypeScript strict mode by @almothafar in #500
- build: enable strict template type-checking by @almothafar in #503
- feat!: upgrade to Angular 22 by @almothafar in #502
- build: go fully zoneless (remove zone.js); upgrade jasmine-core by @almothafar in #505
- fix: float the standalone component dropdown so it overlays content by @almothafar in #506
- build: migrate to @angular/build builders, drop @angular-devkit/build-angular by @almothafar in #507
- docs: document the --ngui-ac-z-index theming variable by @almothafar in #508
- fix(cypress): set explicit rootDir for TypeScript 6 (TS5011) by @almothafar in #509
- docs: clarify publish step, v22 migration, and license holders by @almothafar in #510
Full Changelog: 21.0.0...22.0.0
Revamp, Modern, Angular 21
[21.0.0] — 2026-06-04
⚠️ BREAKING CHANGES
- Requires Angular 21.
peerDependenciesnow require@angular/commonand@angular/core
^21.0.0. Angular 20 and older projects must stay on@ngui/auto-complete@20(or the matching major). - Removed
NguiAutoCompleteModule. The library's last NgModule has been deleted. Import the
standaloneNguiAutoCompleteComponent/NguiAutoCompleteDirectivedirectly instead:
imports: [NguiAutoCompleteComponent, NguiAutoCompleteDirective]. Apps that still need the NgModule
can stay on@ngui/auto-complete@20, which retained it. - The directive is now a
ControlValueAccessor.NguiAutoCompleteDirectiveimplements
ControlValueAccessorand providesNG_VALUE_ACCESSOR, so[(ngModel)],[formControl]and
formControlNameintegrate through Angular forms (with propervalueChanges,touched/dirtystate).
Consequences (seeMIGRATION.mdfor before/after):- Removed the directive's bespoke
ngModelinput and its(ngModelChange)and
(valueChanged)outputs. Use[(ngModel)](Angular still emits(ngModelChange)) or a reactive
form.(valueChanged)has no direct replacement — use(ngModelChange)or the control'svalueChanges. - Removed the directive's custom
[formControl]/formControlNameinputs. The standard Angular
directives now drive it directly — same template syntax, now with full form integration. - Wrapper-
<div>usage: bind the value on the host
(<div ngui-auto-complete [(ngModel)]="x"><input></div>) instead of on a separate inner<input>.
Direct<input ngui-auto-complete [(ngModel)]="x">is unchanged.
- Removed the directive's bespoke
- Unified the selection outputs into one
(valueSelected)event.valueSelected+customSelected
are merged into a single(valueSelected)(on both the component and directive) carrying
NguiAutoCompleteSelection { value, item, index, fromSource }—fromSourceistruefor a list pick,
falsefor a typed value.(customSelected)is removed (checkfromSource: false). The payload changed
from the bare value to this object, so(valueSelected)="x = $event"→(valueSelected)="x = $event.value"
(or use[(ngModel)]/[(value)]for the value). The never-emittedtextEnteredoutput is also
removed.(noMatchFound)is unchanged. - Consolidated value display into one
display-withinput.display-property-nameand the
string-templatevalue-formatterare replaced by a singledisplay-withthat accepts either a
property name or a function:display-with="name"or[display-with]="(item) => …". (list-formatter
still formats the dropdown rows.) Migratedisplay-property-name="name"→display-with="name", and
value-formatter="(key) name"→[display-with]="(item) => '(' + item.key + ') ' + item.name". - Removed the
is-rtlinput. Direction is now auto-detected from the input's computed direction, so
an ancestordir="rtl"(or the document direction) positions the dropdown correctly on its own — no
input and no extra dependency. Replace[is-rtl]="true"withdir="rtl"on the element or an ancestor. - Replaced the
innerHTMLstring templates withTemplateRefs. The stringloading-templateand
header-item-templateinputs are removed. Use theheaderTemplateTemplateRef(already available) and
the newloadingTemplateTemplateRef(loading-textremains for the simple case). This also removes
aninnerHTMLsink. sourceis now a required input.sourceusesinput.requiredon both the component and directive
(it was always required in practice — the control does nothing without it). Omitting[source]is now a
compile-time error under strict templates (and a runtime error otherwise) instead of silently doing
nothing. Just ensure every[ngui-auto-complete]/<ngui-auto-complete>has a[source].- New
@angular/cdkpeer dependency (directive dropdown now uses the CDK Overlay). The
[ngui-auto-complete]directive renders its dropdown through@angular/cdk/overlayinstead of inserting
an absolutely-positioned element next to the input. You must install@angular/cdk@^21and include the
CDK overlay styles once in your app — either@import '@angular/cdk/overlay-prebuilt.css';or any
@angular/materialtheme (which already bundles them). SeeMIGRATION.md.
Added
[(value)]two-way binding onNguiAutoCompleteComponent. The standalone component now exposes a
valuemodel — e.g.<ngui-auto-complete [(value)]="myValue">.(valueSelected)continues to fire.NguiAutoCompleteSelection<T>interface exported for the(valueSelected)payload
({ value, item, index, fromSource }).- Generic
NguiAutoCompleteComponent<T = any>. Binding a typed[source](array or function)
infers the item type, so[(value)],(valueSelected)(NguiAutoCompleteSelection<T>) and the
itemTemplatecontext are all typed without any annotation. Defaults toany, so existing templates
are unaffected. The directive stays loosely typed (Angular can't infer generics for an attribute
directive in templates).
Changed
- Upgraded to Angular 21 (
@angular/*21.2.x,@angular/material+@angular/cdk21.2.x).
Install@ngui/auto-complete@21for Angular 21 projects. - Signal-based inputs/outputs. All
@Input()s are now signalinput()s and all@Output()s are
output()s on both the component and directive (the component's@ViewChilds becameviewChild()
queries). Template bindings are unchanged — every input keeps its existing name/alias (e.g.
min-chars,list-formatter). The only consumer-visible effect is for code that reaches into a
component/directive instance programmatically: those input properties are now read-only signals
(call them, e.g.cmp.minChars()), not plain fields. - Typed attribute coercion. Numeric inputs (
min-chars,max-num-list,z-index) now use
numberAttributeand boolean inputs usebooleanAttribute, so string-attribute forms (min-chars="2")
and bound forms ([min-chars]="2") are both correctly typed. OnPushdropdown component.NguiAutoCompleteComponentnow usesChangeDetectionStrategy.OnPush
and its internal state (dropdownVisible,isLoading,filteredList,minCharsEntered,itemIndex)
is signal-based, so remote/async results and directive-driven updates refresh reliably with less change
detection work. No public API change.- Bumped the library's own
tslibdependency floor to^2.8.1. - The "drop-up" dropdown now anchors with the logical
inset-inline-startinstead ofleft, so it sits
on the correct edge under RTL (matching the directive's positioning). No API change. - CDK Overlay positioning (directive). The dropdown now renders in a CDK overlay at the document root,
so it escapes ancestor clipping / stacking contexts (e.g. inside amat-form-fieldor a card with
overflow: hidden) and flips above/below automatically on overflow. As a result,open-directionis now
a preference (the overlay still flips when there isn't room), andz-indexis rarely needed (the
overlay already layers above page content; it now only orders overlapping overlays). RTL follows the
input's computed direction. Note: because the dropdown is at the document root, custom dropdown
styles (e.g. classes from alist-formatter) must be global, not scoped to an ancestor of the input. - Refreshed, themeable dropdown styling. The dropdown now has a subtle elevation, rounded corners, a
softer border and roomier rows. Appearance is exposed through CSS variables —--ngui-ac-background,
--ngui-ac-color,--ngui-ac-border,--ngui-ac-border-radius,--ngui-ac-shadow,
--ngui-ac-max-height(noneto remove the cap),--ngui-ac-item-padding,--ngui-ac-item-border,
--ngui-ac-hover-backgroundand--ngui-ac-selected-background— each with a sensible default (set them
on:root). See the
README "Theming" section. Applies to the directive and component.
Fixed
- Internal keyword input a11y. The component's internal input (rendered when
show-input-tag) now
carries a uniqueid, clearing the browser's "a form field element should have an id or name" warning.
It is boundstandalone, so it never registers into a consumer's parent<form>(no stray
keywordcontrol) — which also fixes a latent error when the component was used inside a<form>.
Internal (development tooling only — no impact on consumers)
ng updateto Angular 21:@angular/cli+@angular-devkit/build-angular21.2.x,
ng-packagr21.2.5, TypeScript 5.9.3. The demobootstrapApplicationnow provides
provideZoneChangeDetection()(Angular 21 defaults to zoneless; this preserves the existing
zone-based change detection).- ESLint 10. Bumped
eslintand@eslint/jsto 10 andangular-eslintto 21.4.0 (its ESLint peer
now allows^10), unblocking the upgrade deferred in 19.0.0 / 20.0.0. - The directive now forwards inputs to the dynamically created dropdown via
ComponentRef.setInput()
(required now that the component's inputs are read-only signals).
What's Changed
- feat(angular-21)!: upgrade to Angular 21, remove NguiAutoCompleteModule, ESLint 10 by @almothafar in #490
- refactor(lib): signal inputs/outputs + attribute transforms (Phase A, non-breaking) by @almothafar in #491
- chore: add PR template and Copilot/Claude contributor guides by @almothafar in #492
- refactor(lib): OnPush + signal state for the dropdown component (Phase B) by @almothafar in https://github.com/ng2-ui/auto-complete/pu...
Angular 20
[20.0.0] — 2026-06-04
⚠️ BREAKING CHANGES
- Requires Angular 20.
peerDependenciesnow require@angular/commonand@angular/core
^20.0.0. Angular 19 and older projects must stay on@ngui/auto-complete@19. - Removed the unprefixed
[auto-complete]directive selector. Use[ngui-auto-complete]instead
(the directive now matches[ngui-auto-complete]only). Update any templates using the bare
auto-completeattribute:<input auto-complete …>→<input ngui-auto-complete …>.
Added
itemTemplateandheaderTemplateinputs (Angularng-templates) on the component and directive to
customize dropdown rows and the header row, as a typed alternative to the string-basedlist-formatter
/header-item-template. The item template receives the item as$implicitand the rowindex; the
string formatters remain supported and the templates take precedence when provided (fixes #357).open-directioninput (auto|up|down) on the directive and component to control whether the
dropdown opens above or below the input.up/downforce the direction;auto(default) keeps the
previous behaviour of opening above only when the input is near the bottom of the viewport (fixes #386).
Changed
- Upgraded to Angular 20 (
@angular/*20.3.x,@angular/material+@angular/cdk20.2.x).
Install@ngui/auto-complete@20for Angular 20 projects. - Standalone components.
NguiAutoCompleteComponentandNguiAutoCompleteDirectiveare now
standalone.NguiAutoCompleteModuleis retained and re-exports both, so existing
imports: [NguiAutoCompleteModule]consumers keep working unchanged — you can now alternatively
import the standalone component/directive directly. (Full NgModule removal is planned for Angular 21.) inject()DI. Constructor parameter injection across the library was migrated to theinject()
function (no public API change).
Internal (development tooling only — no impact on consumers)
ng updateto Angular 20:@angular/cli+@angular-devkit/build-angular20.3.x,
ng-packagr20.3.2,angular-eslint20.7.0. Workspace migrations applied (schematictype
defaults inangular.json,tsconfigmoduleResolution→bundler).- Bumped
@cypress/schematic4.3 → 5 (now requires Angular 20). - Re-enabled the
@angular-eslint/prefer-standalonelint rule (deferred in 19.0.0). - The demo app was migrated to a standalone
bootstrapApplicationsetup (AppModuleand the routing
NgModule removed in favour ofprovideRouter+app.routes.ts). - Hardened the library component spec so its focus-triggered dropdown reload resolves against a local
source array (Angular 20 / zone.js surfaces the previously-swallowed async error).
Notes
- ESLint 10 remains deferred:
angular-eslint20 still peers on ESLint^8.57 || ^9. It is planned for
the Angular 21 release alongside full NgModule removal.
What's Changed
- feat: upgrade to Angular 20 + standalone/inject migration (v20.0.0) by @almothafar in #483
- feat: ng-template customization for dropdown rows (#357) by @almothafar in #485
- feat: add open-direction input to control dropdown side (#386) by @almothafar in #484
- build: adopt Prettier (printWidth 120) and format the codebase by @almothafar in #486
- chore: modernize issue template to GitHub issue forms by @almothafar in #487
- fix(issue-template): link to README #usage anchor by @almothafar in #488
- build(deps): bump rxjs 7.8.2 and tslib 2.8.1 by @almothafar in #489
Full Changelog: 19.0.0...20.0.0
Angular 19 Support
[19.0.0] — 2026-06-04
Changed
- Upgraded to Angular 19 (
@angular/*19.2.x).peerDependenciesnow require@angular/common
and@angular/core^19.0.0. Install@ngui/auto-complete@19for Angular 19 projects. - Migrated the library template to Angular's built-in control flow syntax (
@if/@forin place of
*ngIf/*ngFor).
Internal (development tooling only — no impact on consumers)
- Migrated ESLint from
.eslintrc.jsonto flat config (eslint.config.js); upgraded ESLint 8 → 9 and
switched to the unifiedangular-eslintandtypescript-eslintpackages. - Bumped dev dependencies to the newest versions compatible with Angular 19:
cypress13 → 15,
@cypress/schematic2 → 4.3,eslint-plugin-cypress3 → 6,jasmine-core+@types/jasmine5 → 6,
@types/node22 → 24,karma-jasmine-html-reporter2.1 → 2.2 (reducesnpm auditfrom 52 to 9). - Added unit specs for the library component and service, and replaced the stale Angular CLI boilerplate
demo specs with workingTestBedsetups.
Notes
- The library remains NgModule-based in this release; the standalone migration is planned for the
Angular 20 release. - ESLint 10,
@cypress/schematic5, and the standalone migration are deferred to the Angular 20 release
(they require Angular 20 / angular-eslint 20).
What's Changed
- fix(demo): suppress built-in no-match row in (noMatchFound) demo card by @almothafar in #478
- feat: upgrade to Angular 19 + control flow migration (v19.0.0) by @almothafar in #479
- test(e2e): fix stale cypress smoke spec for current demo by @almothafar in #481
- docs(changelog): document tooling changes in the 19.0.0 entry by @almothafar in #482
Full Changelog: 18.6.0...19.0.0
Bug Fixes and No Result Event
[18.6.0] — 2026-06-04
Fixed
select-value-ofnow correctly extracts falsy property values (0,null,false,'') from the
selected object — previously the truthiness check caused the raw item to be emitted instead of the
extracted property (fixes #373)
Added
no-match-found-text=""(empty string) now fully suppresses the "No Result Found" row — previously
the empty string fell through to the default text (fixes #307, #292, #198)(noMatchFound)output on both<ngui-auto-complete>component and[ngui-auto-complete]directive —
fires whenever the filtered list is empty andmin-charsthreshold has been met, enabling consumers
to render an "Add new…" affordance
What's Changed
- Pre-phase: demo polish — hero section, toolbar labels, max-width by @almothafar in #469
- fix(demo): constrain tabs width, fix grid alignment, fix Material input styling by @almothafar in #470
- fix(demo): hash routing + no-cache meta to fix GitHub Pages 404 on refresh by @almothafar in #471
- ci: add GitHub Actions CI + fix premature standalone section in README by @almothafar in #472
- fix(ci): add checkout step to deploy-docs job by @almothafar in #473
- fix(demo): remove ES5 browserslist warning & fix Material suffix border by @almothafar in #474
- fix(demo): correct .00 suffix border + show last build time in footer by @almothafar in #475
- fix: select-value-of falsy values + configurable no-match-found (v18.6.0) by @almothafar in #476
- docs(demo): add (noMatchFound) + no-match-found-text demo cards and README updates by @almothafar in #477
Full Changelog: 18.5.0...18.6.0
Revamp Demo and Minor fixes
[18.5.0] — 2026-06-03
Fixed
- Scoped
NguiAutoCompleteServiceper-component instance (was a module singleton — multiple simultaneous
<ngui-auto-complete>components overwrote each other'ssourceproperty causing a runtime crash) isLoadingno longer stays stucktrueafter a failed HTTP request —errorhandler now resets itngOnDestroysubscription teardown: replaced invalidEventEmitter.unsubscribe()calls with proper
RxJSSubscriptionmanagement viadropdownSubs- Replaced
UntypedFormControl/UntypedFormGroupwith typedFormControl/FormGroup - Root
.eslintrc.jsonreferenced non-existente2e/tsconfig.json— removed - Project ESLint configs used file-relative tsconfig paths — changed to workspace-root-relative
demo:prefixinangular.jsonwasdocsinstead ofapp- Removed broken
ctCypress component-test target from the libraryangular.jsonentry
(referenced non-existentauto-complete:servetarget) auto-select-first-itemdemo was missing[auto-select-first-item]="true"— feature was never active
Changed
- Replaced deprecated
karma-coverage-istanbul-reporterwithkarma-coverage - Removed unused
@types/jasminewd2(Protractor artefact, not needed with Cypress) - Pinned
cypressto^13.0.0instead of"latest" - Demo Observable source example replaced from Marvel API (broken auth) to Open Library (free, no key)
- Demo HTTP source examples replaced from Google Maps (requires key) to Nominatim/OpenStreetMap (free, no key)
- RTL demo updated to use Arabic city names with
dir="rtl"scoped to the demo area only
Added
- Angular Material toolbar in demo app with library title and links to GitHub / npm
- Demo examples use
<mat-card>layout in a responsive CSS grid (2-column desktop, 1-column mobile) - Collapsible "View Template" expansion panel per demo example
MatToolbarModule,MatCardModule,MatExpansionModule,MatButtonModuleadded to demo module- Revamped
styles.scss: indigo-pink Material theme, global typography, dark code-block styling - Descriptive subtitles and usage hints on all directive and component demo examples
- Restructured README: badges, API reference table, version-compatibility table, updated dev instructions
What's Changed
- Update app.service.ts by @almothafar in #450
- Bump cookie, socket.io and express by @dependabot[bot] in #451
- Bump postcss and @angular-devkit/build-angular by @dependabot[bot] in #453
- Bump fast-uri from 3.0.1 to 3.1.2 by @dependabot[bot] in #452
- Bump follow-redirects from 1.15.9 to 1.16.0 by @dependabot[bot] in #455
- Bump lodash from 4.17.21 to 4.18.1 by @dependabot[bot] in #456
- Bump ip-address and socks by @dependabot[bot] in #457
- Bump minimatch from 3.1.2 to 3.1.5 by @dependabot[bot] in #458
- Bump flatted from 3.3.1 to 3.4.2 by @dependabot[bot] in #459
- Bump qs, body-parser and @cypress/request by @dependabot[bot] in #460
- Phase 1: pre-upgrade cleanup + demo revamp (v18.5.0) by @almothafar in #464
Full Changelog: 18.0.0...18.5.0
Angular 18 Support
[18.0.0] Major Update
- Upgraded to support Angular 18
- Migration for deprecated Observable params
- Adding e2e smock test for the project removing deprecated protractor adding cypress
What's Changed
- E2E tests by @almothafar in #445
- Angular 18 upgrade by @almothafar in #446
- Fix demo and docs by @almothafar in #447
- RxJS 7 migration by @almothafar in #448
- Update docs by @almothafar in #449
Full Changelog: 17.0.0...18.0.0
Angular 17 Support
[17.0.0] Major Update
- Upgraded to support Angular 17
What's Changed
- Angular 17 Upgrade by @almothafar in #444
Full Changelog: 16.0.0...17.0.0
Angular 16 Support
[16.0.0] Major Update
- Upgraded to support Angular 16
What's Changed
- Upgrade Angular to version 16 by @almothafar in #443
Full Changelog: 15.0.0...16.0.0
Angular 15 Support
[15.0.0] Major Update
- Upgraded to support Angular 15
- Remove deprecated modules and services
- Refactor code base splitting SCSS and HTML to separated files
- Fix Demo/Docs project
What's Changed
- Angular 15 Upgrade by @almothafar in #442
Full Changelog: 14.0.0...15.0.0