DEV Community

Alexandro Paixao Marques
Alexandro Paixao Marques

Posted on • Edited on

Angular 22 Multiselect Dropdown: A Migration-Friendly Component with Live Functional Tests


Modern Angular applications rarely need just a dropdown.

In real projects, a multiselect dropdown usually sits inside something more important: filters, dashboards, reporting tools, permission editors, workflow screens, admin panels, and data-heavy forms where users need to search, group, select, clear, validate, and keep state consistent. It is almost never the feature. It is the control that everything else in the form depends on.

That is the context behind Stackline Angular Multiselect Dropdown, now available for Angular 22.

Angular 22 is a meaningful release to target. It landed in early June 2026 as the version where the "signal-first" direction stopped being a roadmap and became the default: zoneless change detection stays the default for new projects, OnPush becomes the default change-detection strategy for new components, Signal Forms graduate to stable, the Angular Aria accessibility primitives are now stable, the toolchain floor moves up to TypeScript 6, and Vitest replaces Karma/Jasmine as the default test runner. A lot of teams will be upgrading specifically to get onto a fresh long-term-support window with that complete feature set.

This release of the library is not just about making a dropdown compile on the latest Angular version. The goal is to provide a practical component that can be adopted in real applications, exercised through live examples, and migrated gradually without forcing teams to rewrite every existing template at once — even while the framework underneath them is going through its biggest mental-model shift in years.

Install the Angular 22 line with:

npm install @stackline/angular-multiselect-dropdown
Enter fullscreen mode Exit fullscreen mode

Links:

npm:
https://www.npmjs.com/package/@stackline/angular-multiselect-dropdown

Documentation (Angular 22):
https://alexandro.net/docs/angular/multiselect/angular-22/

Live demo / interactive playground (StackBlitz):
https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-22?startScript=start&initialpath=%2Fbasic

GitHub:
https://github.com/alexandroit/angular-multiselect-dropdown

For new releases, documentation updates, and upcoming Angular components, visit:
https://alexandro.net

What the library provides

Stackline Angular Multiselect Dropdown is an Angular multiselect component designed for real application forms, dashboards, filters, and enterprise interfaces.

It supports:

  • single-select and multi-select modes
  • search and filtering
  • select all and clear all behavior
  • grouped options
  • custom item templates with selected and ARIA context
  • custom badge templates
  • a renderless state helper for fully custom HTML
  • template-driven forms
  • reactive forms
  • lazy loading, remote-data hooks, and a virtual-scrolling example for very large lists
  • accessibility-focused keyboard navigation, focus handling, and a documented ARIA contract
  • CSS and SCSS theming through a skin system
  • versioned documentation per Angular major
  • modern selector support with legacy selector compatibility

A multiselect component can look simple from the outside, but once it is used across several forms and workflows, replacing it becomes expensive. It affects templates, validation, events, styling, selected state, form reset behavior, focus and keyboard behavior, and sometimes even backend query logic. The cost is rarely in the first screen. It is in the twentieth screen that quietly depends on the behavior of the first.

That is why compatibility, predictable APIs, accessibility, and safe migration paths matter more than a long feature list.

Why this package exists

There are many dropdowns and select components available for Angular, but the hard part in real applications is rarely the first implementation.

The hard part is keeping the component stable while Angular moves forward, while forms evolve, while UI layouts become more complex, while accessibility requirements get audited, and while existing screens continue to depend on older selectors or configuration patterns.

This is especially true right now. Angular 22 is the third release in a deliberate transformation. Signals arrived, zoneless change detection went from preview to default, standalone APIs became the norm, and the framework has been steadily reducing how much RxJS and Zone.js machinery you need for everyday UI state. That progress is good, but it also means a lot of production code is mid-migration: partly modern, partly classic, and very sensitive to anything that forces a rewrite.

This package focuses on a practical set of goals:

  • keep Angular 22 compatibility clear and validated, not optimistic
  • keep the API familiar for existing projects so upgrades do not become rewrites
  • support both template-driven and reactive forms
  • ship a documented keyboard and ARIA contract instead of leaving accessibility as an afterthought
  • provide working examples that can be tested in the browser before installing
  • preserve a migration path for older templates and selectors
  • expose enough configuration for real dashboard and form use cases, and a renderless mode for the cases that need full control

The intention is not to reinvent how selection works. The intention is to make a commonly needed UI component easier to adopt, validate, and maintain across a framework that is changing quickly underneath it.

Angular 22 in context

It helps to be explicit about what Angular 22 actually changes, because it shapes how any third-party component should behave in a 2026 codebase.

Area Angular 21 Angular 22
Change detection Zoneless default for new projects Zoneless default; OnPush is the default strategy for new components
Forms Signal Forms introduced as experimental Signal Forms stable and production-ready
Accessibility Angular Aria in developer preview Angular Aria primitives stable
Components Standalone the norm Selectorless components (import directly in templates) maturing
TypeScript 5.x supported TypeScript 6 required; 5.9 and older dropped
Testing Vitest opt-in Vitest as the default, faster test runner
Tooling MCP server support MCP/AI tooling stabilized

The takeaway is that most of what the Angular 21 notes described as "coming" or "try this" is now the recommended path. The framework is firmly signal-first, but it is also explicit that this is progressive modernization rather than a forced rewrite — signals coexist with RxJS, and Zone.js is still supported for existing apps.

Where does a classic settings-driven multiselect fit in that world? Honestly, it is not a signal-native control, and this is a deliberate design choice rather than an oversight. Enterprise Angular codebases still contain large amounts of NgModule-based composition and template-driven or reactive forms that work perfectly well and are not getting rewritten just because OnPush is now a default. This package leans into that: it ships as an NgModule with the classic API on purpose, so a team can move its build to Angular 22 without simultaneously rewriting every form that touches the dropdown. For the cases that do want a fully modern, custom surface, the renderless state helper (covered below) lets you own the rendering and wiring while the library handles selection, item identity, filtering, object preservation, and ARIA state.

Installation

For Angular 22 projects, install the validated 22.x line with an exact version:

npm install @stackline/angular-multiselect-dropdown@22.0.1 --save-exact
Enter fullscreen mode Exit fullscreen mode

Pinning the version with --save-exact keeps compatibility predictable across local environments, CI pipelines, and production builds. The 22.0.1 patch keeps the tested Angular 22 behavior, makes <angular-multiselect> the documented standard selector, keeps <angular2-multiselect> only as a legacy compatibility alias, and ships the accessibility and keyboard/ARIA interaction contract.

There is one intentional exception to the usual strict peer ranges. The Angular 22 line uses >=22.0.0 <24.0.0 instead of bounding only to Angular 22. That lets Angular 23 projects install the package on launch day while the dedicated Angular 23 validation line is being prepared, without weakening the compatibility story for everyone else. The package was tested in a real Angular 22.0.0 application before publication.

Module registration

The component is exposed through AngularMultiSelectModule.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AngularMultiSelectModule } from '@stackline/angular-multiselect-dropdown';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    AngularMultiSelectModule
  ]
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

Angular 22 does not force you off NgModules. The framework keeps backward compatibility, and module-based registration is still a first-class way to compose an application. Registering this module remains the supported path, and it is also what makes the component drop cleanly into existing module-based screens that you are not planning to convert to standalone right now. After registering the module, the component can be used in templates with a data source, selected values, and a settings object.

Basic usage

A typical implementation starts with a list of items, a selected model, and a dropdown configuration.

countries = [
  { id: 1, itemName: 'Brazil' },
  { id: 2, itemName: 'Canada' },
  { id: 3, itemName: 'Portugal' },
  { id: 4, itemName: 'United States' }
];

selectedCountries = [
  { id: 2, itemName: 'Canada' }
];

dropdownSettings = {
  singleSelection: false,
  text: 'Select countries',
  selectAllText: 'Select all',
  unSelectAllText: 'Clear all',
  enableCheckAll: true,
  enableSearchFilter: true,
  searchPlaceholderText: 'Search',
  badgeShowLimit: 4,
  maxHeight: 260,
  showCheckbox: true,
  noDataLabel: 'No data',
  skin: 'classic',
  primaryKey: 'id',
  labelKey: 'itemName',
  tagToBody: false
};
Enter fullscreen mode Exit fullscreen mode
<angular-multiselect
  [data]="countries"
  [(ngModel)]="selectedCountries"
  [settings]="dropdownSettings">
</angular-multiselect>
Enter fullscreen mode Exit fullscreen mode

This keeps the template compact while allowing most of the behavior to be configured from TypeScript. Note the skin key: in the Angular 22 line, styling is selected through skin (classic or material). The older theme key is still accepted as a legacy alias for existing code, but new usage should configure skin.

Selector compatibility

The recommended selector for new code is:

<angular-multiselect></angular-multiselect>
Enter fullscreen mode Exit fullscreen mode

The package also keeps support for the older selector:

<angular2-multiselect></angular2-multiselect>
Enter fullscreen mode Exit fullscreen mode

This matters in large Angular applications where selectors may already exist across shared modules, reusable form components, admin screens, internal libraries, and older templates.

Teams can upgrade gradually instead of rewriting everything in one pass. Existing applications can continue working while new development standardizes around the modern selector. That kind of migration flexibility is exactly what you want during an Angular 22 upgrade, where the framework change itself is already enough work without dragging every component rename into the same pull request.

Settings-driven behavior

One of the strongest parts of the package is the settings-driven API.

Most dropdown behavior can be configured through a single settings object instead of requiring wrapper components or repeated template changes.

Supported settings include:

  • singleSelection
  • enableCheckAll
  • enableSearchFilter
  • searchBy
  • searchPlaceholderText
  • searchAutofocus
  • maxHeight
  • badgeShowLimit
  • limitSelection
  • disabled
  • groupBy
  • selectGroup
  • showCheckbox
  • noDataLabel
  • lazyLoading
  • labelKey
  • primaryKey
  • ariaLabel
  • keyboard
  • position
  • autoPosition
  • addNewItemOnFilter
  • escapeToClose
  • clearAll
  • skin (legacy alias: theme)
  • tagToBody (alias: appendToBody)

Single selection without checkboxes

dropdownSettings = {
  singleSelection: true,
  showCheckbox: false,
  enableCheckAll: false,
  text: 'Select one country'
};
Enter fullscreen mode Exit fullscreen mode

Selection limit

dropdownSettings = {
  singleSelection: false,
  limitSelection: 2,
  badgeShowLimit: 2,
  text: 'Select up to 2 countries'
};
Enter fullscreen mode Exit fullscreen mode

Grouped data

countries = [
  { id: 1, itemName: 'Brazil', region: 'South America' },
  { id: 2, itemName: 'Canada', region: 'North America' },
  { id: 3, itemName: 'Portugal', region: 'Europe' }
];

dropdownSettings = {
  groupBy: 'region',
  enableSearchFilter: true,
  text: 'Select countries by region'
};
Enter fullscreen mode Exit fullscreen mode

This approach keeps behavior explicit and discoverable for consumers. A single settings object is also easy to standardize and share across an application, which matters more than it sounds: the most common cause of "the dropdown behaves slightly differently on this screen" is ten slightly different settings objects scattered across ten components.

Search and filtering

Search becomes important as soon as datasets grow.

The package supports filtering through enableSearchFilter, while searchBy allows filtering only specific fields.

dropdownSettings = {
  enableSearchFilter: true,
  searchPlaceholderText: 'Search countries',
  searchBy: ['itemName', 'region']
};
Enter fullscreen mode Exit fullscreen mode

This gives teams two useful modes:

  • broad search across item properties
  • controlled search over selected fields

Controlled search is useful when items contain internal IDs, flags, system fields, or hidden metadata that should not match the user input. For applications with complex objects, predictable search behavior avoids confusing matches — a user typing "12" should not silently match an internal id of 12 unless you decided that on purpose.

Keyboard and accessibility

This is the part of the Angular 22 line that deserves the most attention, and it lines up directly with Angular Aria becoming stable in the framework.

Accessibility in a multiselect is not a single attribute. It is a behavior contract: what the keyboard does on the trigger versus inside the list, how focus moves, how selected chips are announced, and what screen readers report for each option. The package exposes that contract through a keyboard settings object so you can configure it instead of fighting it.

dropdownSettings = {
  text: 'Keyboard-tested countries',
  enableSearchFilter: true,
  searchAutofocus: false,
  keyboard: {
    space: true,
    spaceOptionAction: 'toggle',
    tab: true,
    arrows: true,
    escape: true,
    backspaceRemovesLastWhenSearchEmpty: false,
    deleteRemovesFocusedBadge: true
  }
};
Enter fullscreen mode Exit fullscreen mode

The default behavior is designed to match what users expect from a real combobox:

  • Space on the trigger opens or closes the dropdown.
  • Space on an option toggles that option and keeps focus on it.
  • Search inputs type a normal space, so searching is never hijacked by selection logic.
  • Tab moves focus and never accidentally selects an option.
  • Escape closes the list without clearing the selected values.
  • Empty-search Backspace does not remove selected values by default, which prevents accidental data loss.
  • A focused badge or remove button can be removed intentionally with Backspace or Delete.
  • Options expose matching aria-selected and aria-checked values, so assistive technology reports a consistent state.

The Angular line follows the same combobox contract that was validated in the related React 19.1.x work, then exposed through Angular settings. Carrying one tested interaction model across both frameworks means the behavior is not reinvented per platform, and the edge cases that usually break accessibility — space inside search, tab stealing a selection, escape wiping a form field — were handled deliberately rather than by accident.

Custom templates

A multiselect becomes more useful when consumers can control how dropdown items and selected badges are rendered. In the Angular 22 line, the item template context is richer: alongside item, you also receive label, selected, and ariaChecked, so custom rendering can reflect selection and accessibility state without you recomputing it.

Custom item template

<c-item>
  <ng-template
    let-item="item"
    let-label="label"
    let-selected="selected"
    let-ariaChecked="ariaChecked">
    <span [attr.data-aria-checked]="ariaChecked">
      {{ label }}
      <strong *ngIf="selected">Selected</strong>
    </span>
  </ng-template>
</c-item>
Enter fullscreen mode Exit fullscreen mode

Custom badge template

<c-badge>
  <ng-template let-item="item">
    <span class="country-chip">{{ item.itemName }}</span>
  </ng-template>
</c-badge>
Enter fullscreen mode Exit fullscreen mode

Complete custom template example

<angular-multiselect
  [data]="countries"
  [(ngModel)]="selectedCountries"
  [settings]="dropdownSettings">

  <c-badge>
    <ng-template let-item="item">
      <span class="country-chip">{{ item.itemName }}</span>
    </ng-template>
  </c-badge>

  <c-item>
    <ng-template
      let-item="item"
      let-label="label"
      let-selected="selected"
      let-ariaChecked="ariaChecked">
      <strong>{{ label }}</strong>
      <small>{{ item.region }}</small>
    </ng-template>
  </c-item>

</angular-multiselect>
Enter fullscreen mode Exit fullscreen mode

This is useful when applications need avatars, icons, tags, role indicators, custom layouts, region labels, permission markers, account types, or status badges. Most business interfaces eventually need more than plain text rendering, and exposing selected and ariaChecked in the template context means the visual state and the accessible state stay in sync instead of drifting apart.

Renderless state helper

For the cases where settings and templates are not enough, the Angular 22 line ships a renderless (headless) state helper. This is the part that fits the signal-first, "own your rendering" direction of modern Angular: you write all of the HTML, and the library gives you selection, filtering, item identity, object preservation, and ARIA state.

Use AngularMultiselectState when you want Stackline behavior under fully custom markup:

import {
  AngularMultiselectState,
  defineAngularMultiselectSettings
} from '@stackline/angular-multiselect-dropdown';

interface CountryOption {
  id: number;
  itemName: string;
  region: string;
}

state = new AngularMultiselectState<CountryOption>({
  data: countries,
  selectedItems: [countries[0]],
  settings: defineAngularMultiselectSettings<CountryOption>({
    primaryKey: 'id',
    labelKey: 'itemName',
    searchBy: ['itemName', 'region'],
    ariaLabel: 'Headless country picker'
  }),
  onChange: (items) => {
    selectedItems = items;
  }
});
Enter fullscreen mode Exit fullscreen mode

The documentation includes a dedicated headless and ARIA route that binds the returned trigger, listbox, and option state into fully custom Angular HTML. Practically, this lets a design system build its own visual component on top of a tested selection engine, instead of either fighting the default rendering or rebuilding selection logic from scratch.

Forms integration

A production-ready dropdown component must integrate correctly with Angular forms.

The package supports both template-driven forms and reactive forms.

Template-driven forms

<form #form="ngForm">
  <angular-multiselect
    [data]="countries"
    [(ngModel)]="selectedCountries"
    [settings]="dropdownSettings"
    name="countries"
    required>
  </angular-multiselect>
</form>
Enter fullscreen mode Exit fullscreen mode

Reactive forms

<form [formGroup]="userForm">
  <angular-multiselect
    [data]="countries"
    [settings]="dropdownSettings"
    formControlName="countries">
  </angular-multiselect>
</form>
Enter fullscreen mode Exit fullscreen mode

In real applications, a multiselect value is not only a visual state. It needs to participate in validation, dirty and touched state, serialization, reset behavior, disabled state, and form submission.

A word on Angular 22 specifically: Signal Forms are now stable, and many new projects will reach for them. The Angular team has been explicit that forms interoperability is a priority and that the reactive and template-driven systems are not going away. This component integrates through the classic ControlValueAccessor path, which keeps it working inside existing template-driven and reactive forms during a migration. If a screen is rebuilt around Signal Forms, the renderless state helper is the cleaner bridge, because it hands you the selected items through onChange and lets you drive a signal yourself. Clean forms integration reduces custom glue code and keeps the component maintainable across large codebases that are part-modern, part-classic.

Event system

The component exposes a classic Angular event model for selection workflows.

<angular-multiselect
  [data]="countries"
  [(ngModel)]="selectedCountries"
  [settings]="dropdownSettings"
  (onSelect)="onItemSelect($event)"
  (onDeSelect)="onItemDeSelect($event)"
  (onSelectAll)="onSelectAll($event)"
  (onDeSelectAll)="onDeSelectAll($event)"
  (onAddFilterNewItem)="onAddNewItem($event)">
</angular-multiselect>
Enter fullscreen mode Exit fullscreen mode

Selection events are useful when dropdown changes need to trigger downstream behavior, such as refreshing a report, loading dependent filters, updating query parameters, syncing form state, sending analytics events, enabling related controls, or validating dependent fields.

In many applications, a selection change is not isolated. It is part of a larger workflow. A predictable, stable event contract makes that easier to manage — and keeping the same output names across versions means the upgrade to Angular 22 does not silently break the handlers you already wrote.

Lazy loading, virtual scrolling, and large lists

Large datasets are where simple dropdowns usually start failing.

The package includes lazy loading support and remote-data hooks.

dropdownSettings = {
  text: 'Select items',
  enableSearchFilter: true,
  lazyLoading: true,
  labelKey: 'name',
  primaryKey: 'id',
  maxHeight: 260
};
Enter fullscreen mode Exit fullscreen mode

This matters for applications dealing with users, customers, products, permissions, locations, departments, catalogs, tags, or reporting dimensions. A component that supports lazy loading can be integrated with local pagination, server-side filtering, remote search workflows, and large-list scenarios.

The Angular 22 documentation also adds a dedicated virtual-scrolling example for very large option sets, alongside the lazy-loading and remote-data examples. The distinction is worth understanding: lazy loading is about fetching more data as the user scrolls or searches, while virtual scrolling is about rendering only the visible rows of a list that is already in memory. Large enterprise lists often need both — fetch in pages, render a window — and having a working example for each keeps you from guessing which problem you actually have.

One important detail for async data: the Angular 22 line preserves the selected objects across asynchronous refreshes. When a remote call replaces the option list, previously selected items are not silently dropped just because the array reference changed. That is exactly the kind of bug that is invisible in a small demo and painful in production.

Dialogs and overflow containers

Dropdown positioning problems usually appear only in real layouts.

A dropdown that works on a simple page can behave differently inside dashboard cards, modals, side panels, scrollable containers, constrained widgets, table filters, and embedded panels.

The package exposes configuration options such as position, autoPosition, and tagToBody (also accepted as appendToBody).

For sticky cards, constrained containers, or dashboard layouts, keep tagToBody: false so the dropdown panel stays anchored to the field and does not jump across the page.

Use tagToBody: true when the dropdown is inside Angular Material dialogs, modals, drawers, or any container that sets overflow: hidden or overflow: auto:

settings = {
  text: 'Select countries',
  enableSearchFilter: true,
  skin: 'material',
  tagToBody: true
};
Enter fullscreen mode Exit fullscreen mode

With tagToBody: true, the open panel renders outside the clipping container, stays aligned to the original trigger, keeps the menu surface opaque, recalculates position on scroll and resize, and cleans itself up on close or destroy. The opaque-surface and dialog-safe positioning behavior is carried forward from the Angular 21.2.x baseline, so the upgrade does not regress the hard-won layout fixes.

Theming strategy

The package ships with bundled CSS and SCSS, and styling is selected through the skin setting (classic or material). skin replaces the older theme key; theme still works as a legacy alias so existing code keeps rendering.

A default theme can be added through the Angular styles configuration:

{
  "styles": [
    "node_modules/@stackline/angular-multiselect-dropdown/themes/default.theme.css"
  ]
}
Enter fullscreen mode Exit fullscreen mode

The package also ships a full custom starter theme in both formats, so there are two adoption paths.

Fast adoption

Use the bundled CSS theme directly.

{
  "styles": [
    "node_modules/@stackline/angular-multiselect-dropdown/themes/default.theme.css"
  ]
}
Enter fullscreen mode Exit fullscreen mode

Design-system control

Start from the SCSS theme file, keep it in your application source, and adapt the selectors and tokens to your design system.

{
  "styles": [
    "src/styles.scss",
    "src/styles/multiselect-dropdown.theme.scss"
  ]
}
Enter fullscreen mode Exit fullscreen mode

Switching skins at runtime is just a settings change:

settings = { text: 'Classic basic', skin: 'classic' };
materialSettings = { text: 'Material basic', skin: 'material' };
Enter fullscreen mode Exit fullscreen mode

This gives teams a working default while still allowing deeper customization when the component needs to match an internal design system. The css starter is for teams that want a plain compiled file they can copy and adjust without a Sass pipeline; the scss starter is for teams that want to take over the component styling completely.

Live functional examples and StackBlitz playground

One of the strongest parts of the Angular 22 release is the live functional documentation.

The Angular 22 documentation includes real interactive examples running in a live Angular environment, and the editable playground is a single Angular 22 StackBlitz with isolated lazy routes. The official links use stackblitz.com/github against the maintained GitHub repository, so they stay tied to the latest pushed source instead of creating stale forked copies for every example. Each example has its own folder, Angular module, data object, and URL.

The Angular 22 examples cover:

  1. basic multi-select
  2. single selection
  3. search and select all
  4. custom search from an API
  5. search filter by property
  6. search and add a new item
  7. grouped datasets
  8. custom item and badge templating
  9. template-driven forms
  10. reactive forms
  11. virtual scrolling
  12. lazy loading from an API
  13. remote data
  14. using the control in a list / for loop
  15. using the dropdown inside a dialog
  16. multiple dropdowns on one page
  17. dynamic data loading
  18. component methods
  19. events
  20. disabled mode
  21. selection limits
  22. badge overflow limits
  23. custom placeholder and styling

These examples are not just static documentation. They let developers check the behavior directly in the browser before installing the package. That matters because UI components are usually judged by edge cases: how search behaves, how selected values are displayed, how empty states look, how limits are handled, how keyboard navigation feels, and how the component reacts in real interaction. For UI libraries, live examples are part of the trust model.

Official Angular 22 test matrix

The Angular 22 release was validated in a real Angular 22.0.0 application using @stackline/angular-multiselect-dropdown@22.0.1. The documentation reuses the same example pattern from that clean test app, including the accessibility-focused keyboard, focus, and ARIA behavior, responsive dropdown width handling, opaque menu surfaces, and dialog-safe positioning carried forward from the Angular 21.2.x line.

The same twelve scenarios are validated for both the classic and material skins.

# Scenario Main settings tested
01 Basic multi { enableSearchFilter: false }
02 Search + select all search, select all, clear all, events
03 Single without checkbox { singleSelection: true, showCheckbox: false, enableCheckAll: false }
04 Multi without checkbox { showCheckbox: false, enableCheckAll: false }
05 Selection limit { limitSelection: 2, badgeShowLimit: 2 }
06 Badge overflow { badgeShowLimit: 2, maxHeight: 220 }
07 Grouped by region { groupBy: 'region', maxHeight: 220 }
08 Disabled with value { disabled: true }
09 Empty data { noDataLabel: 'No records found' }
10 Long list with scroll { maxHeight: 120, badgeShowLimit: 3 }
11 Local lazy loading { lazyLoading: true, maxHeight: 120, badgeShowLimit: 3 }
12 Item + chip template <c-badge> and <c-item> custom templates

Publishing the exact scenarios and settings that were tested is a small thing that pays off during adoption: instead of trusting a "tested on Angular 22" badge, you can see precisely which configurations were exercised, and reproduce them.

Angular version strategy

Many Angular libraries use broad peer dependency ranges. That can look convenient, but it often creates uncertainty. A package may install successfully while still not being clearly validated against the Angular version used in production.

This package follows a stricter strategy where each Angular major receives its own validated package line, locked to one framework major. The compatibility table in the repository maps each package family to its Angular family, its peer range, and the tested release window — all the way back from Angular 22 to Angular 2.

That improves reproducible builds, compatibility validation, migration planning, CI predictability, and versioned-documentation consistency.

The Angular 22 line is the one deliberate exception. Its peer range is >=22.0.0 <24.0.0 rather than being bounded to Angular 22 alone, so Angular 23 projects can install it on launch day while the dedicated Angular 23 validation line is prepared. Angular 21 stays bounded at >=21.0.0 <22.0.0. The point is to give Angular 23 early adopters a working install path without pretending the package has already been validated against a framework version that may not have shipped yet.

For Angular teams, predictable compatibility is usually more valuable than optimistic version ranges, and being explicit about the one place the range is loosened is part of keeping that trust.

Migration checklist

For teams adopting the Angular 22 line, I would use the following checklist.

1. Get onto a supported Angular version first

Angular follows an 18-month lifecycle (6 months active support, 12 months LTS). Angular 19 reached end-of-life on May 19, 2026, and everything below Angular 20 is unsupported. Separate the framework upgrade from pattern modernization: reach Angular 22 first, then adopt signals, Signal Forms, and selectorless components incrementally.

2. Install the package

npm install @stackline/angular-multiselect-dropdown@22.0.1 --save-exact
Enter fullscreen mode Exit fullscreen mode

3. Register the module

import { AngularMultiSelectModule } from '@stackline/angular-multiselect-dropdown';
Enter fullscreen mode Exit fullscreen mode

4. Add a theme

{
  "styles": [
    "node_modules/@stackline/angular-multiselect-dropdown/themes/default.theme.css"
  ]
}
Enter fullscreen mode Exit fullscreen mode

5. Move theme to skin

Update settings objects to use skin: 'classic' or skin: 'material'. Leave theme only where you have not migrated yet, since it still works as a legacy alias.

6. Use the modern selector for new code

<angular-multiselect></angular-multiselect>
Enter fullscreen mode Exit fullscreen mode

7. Keep the legacy selector only where needed during migration

<angular2-multiselect></angular2-multiselect>
Enter fullscreen mode Exit fullscreen mode

8. Verify form behavior

Check initial selected values, reset behavior, required validation, disabled state, reactive form bindings, and template-driven form bindings. If a screen is being rebuilt on Signal Forms, plan to bridge through the renderless state helper.

9. Verify keyboard and accessibility

Confirm that space inside the search input types a space, that tab does not select an option, that escape closes without clearing the field, and that options report consistent aria-selected and aria-checked. Configure the keyboard settings object if your application needs different behavior.

10. Validate real UI scenarios

Test the dropdown inside modals, scrollable containers, dashboard cards, table filters, side panels, and forms with validation messages. Use tagToBody: true (or appendToBody: true) for dialogs and overflow-clipped containers.

11. Review large-list behavior

For large datasets, evaluate lazyLoading, virtual scrolling, maxHeight, search behavior, server-side filtering, scroll-to-end handling, and selected-object preservation across async refreshes.

12. Standardize settings

Create shared settings presets for your design system.

export const defaultMultiselectSettings = {
  singleSelection: false,
  enableCheckAll: true,
  enableSearchFilter: true,
  badgeShowLimit: 4,
  maxHeight: 260,
  showCheckbox: true,
  skin: 'classic',
  primaryKey: 'id',
  labelKey: 'itemName'
};
Enter fullscreen mode Exit fullscreen mode

This avoids slightly different dropdown behavior across the same application.

When this component is a good fit

This package is a strong fit when you need:

  • Angular 22 compatibility, validated rather than assumed
  • classic Angular module integration that drops into existing NgModule screens
  • template-driven and reactive forms support during a migration
  • search, select-all, grouping, and selection limits
  • a documented keyboard and ARIA contract, aligned with Angular Aria
  • customizable item and badge rendering, with selected and ARIA context in the template
  • a renderless mode for fully custom HTML on top of a tested selection engine
  • theming through CSS and SCSS via a skin system
  • migration-friendly selector compatibility
  • lazy loading, virtual scrolling, and object preservation for large async lists
  • live examples and a StackBlitz playground to evaluate before adoption
  • bounded, per-major Angular version support

It is especially useful for Angular applications where stability and migration control matter more than replacing every UI control from scratch.

It is probably not the right choice if you are starting a brand-new, fully signal-first application with no legacy forms and you want a component built natively around signals and selectorless composition. In that case, either use the renderless state helper as the foundation and build your own surface on top of it, or pick a signal-native control. Being clear about that boundary is part of the package being trustworthy: it is optimized for continuity, not for being the most modern thing on the page.

Final thoughts

A good UI component is not only about what appears on the screen.

In real Angular projects, the important questions are practical: Does it integrate cleanly with forms? Does it preserve state correctly across async refreshes? Is it accessible by keyboard and to screen readers? Can teams migrate without rewriting templates? Does it handle larger datasets? Can the design system customize it? Are the examples reproducible? Is Angular compatibility clearly validated?

Stackline Angular Multiselect Dropdown for Angular 22 focuses on those concerns. The package includes search, grouping, select-all support, custom templates, a documented keyboard and ARIA contract, a renderless state helper, form integration, theming through skins, lazy loading and virtual scrolling, and live Angular 22 examples running in a real application environment.

The migration path is also practical. Existing applications can keep their NgModule registration, classic API, and legacy selectors while newer projects adopt the modern selector and renderless mode progressively — which is exactly the posture Angular 22 itself takes toward modernization. For teams building or upgrading Angular 22 applications during the signal-first transition, that combination of validated compatibility, accessibility, customization, and reproducible live examples makes the package a solid option for production use.

For new releases, documentation updates, and upcoming Angular components, visit:

https://alexandro.net

Links

npm:
https://www.npmjs.com/package/@stackline/angular-multiselect-dropdown

Documentation (Angular 22):
https://alexandro.net/docs/angular/multiselect/angular-22/

Live demo / interactive playground (StackBlitz):
https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-22?startScript=start&initialpath=%2Fbasic

GitHub:
https://github.com/alexandroit/angular-multiselect-dropdown

All Angular lines (Angular 2 to Angular 22):
https://alexandro.net/docs/angular/multiselect/

Top comments (0)