@stackline/angular-multiselect-dropdown 21.1.14 → 21.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @stackline/angular-multiselect-dropdown
|
|
2
2
|
|
|
3
|
-
> A maintained Angular multiselect dropdown for classic Angular forms workflows, with search, grouping, custom item and badge templates, lazy loading, custom CSS/SCSS theming,
|
|
3
|
+
> A maintained Angular multiselect dropdown for classic Angular forms workflows, with search, grouping, custom item and badge templates, lazy loading, custom CSS/SCSS theming, accessibility-focused and keyboard/ARIA tested support, and support for both template-driven and reactive forms.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@stackline/angular-multiselect-dropdown)
|
|
6
6
|
[](https://www.npmjs.com/package/@stackline/angular-multiselect-dropdown)
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
[](https://www.typescriptlang.org)
|
|
11
11
|
[](https://github.com/alexandroit/angular-multiselect-dropdown/stargazers)
|
|
12
12
|
|
|
13
|
-
**[Documentation & Live Demos](https://alexandro.net/docs/angular/multiselect/)** | **[Angular 21 Demo](https://alexandro.net/docs/angular/multiselect/angular-21/)** | **[npm](https://www.npmjs.com/package/@stackline/angular-multiselect-dropdown)** | **[Issues](https://github.com/alexandroit/angular-multiselect-dropdown/issues)** | **[Repository](https://github.com/alexandroit/angular-multiselect-dropdown)**
|
|
13
|
+
**[Documentation & Live Demos](https://alexandro.net/docs/angular/multiselect/)** | **[Angular 21 Demo](https://alexandro.net/docs/angular/multiselect/angular-21/)** | **[StackBlitz Playground](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fbasic)** | **[npm](https://www.npmjs.com/package/@stackline/angular-multiselect-dropdown)** | **[Issues](https://github.com/alexandroit/angular-multiselect-dropdown/issues)** | **[Repository](https://github.com/alexandroit/angular-multiselect-dropdown)**
|
|
14
14
|
|
|
15
|
-
**Latest tested package release:** `21.
|
|
15
|
+
**Latest tested package release:** `21.2.0` for Angular `21.x`
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
|
|
25
25
|
The original `angular2-multiselect-dropdown` package became difficult to keep current across multiple Angular generations. This maintained package keeps the classic API and template structure intact, introduces the new primary selector `<angular-multiselect>`, preserves the legacy alias `<angular2-multiselect>`, and publishes the project line by line so older applications can keep a predictable upgrade path.
|
|
26
26
|
|
|
27
|
-
The repository contains the full documentation matrix from Angular 2 through Angular 21. The current package release is `21.
|
|
27
|
+
The repository contains the full documentation matrix from Angular 2 through Angular 21. The current tested package release is `21.2.0` for Angular 21.x applications.
|
|
28
28
|
|
|
29
|
-
The Angular 21 package is compatible with Angular 21.x and was tested in a real Angular 21.2.14 application before npm publication. The 21.
|
|
29
|
+
The Angular 21 package is compatible with Angular 21.x and was tested in a real Angular 21.2.14 application before npm publication. The 21.2.0 release includes accessibility-focused keyboard navigation, focus handling, and ARIA support for the dropdown trigger, clear-all action, selected chips, listbox, and lazy-loaded results. It ports the React 19.1.x combobox contract into Angular patterns: configurable keyboard behavior, matching `aria-selected` plus `aria-checked`, selected-object preservation across async data refreshes, richer template contexts, and renderless state helpers for custom Angular HTML.
|
|
30
30
|
|
|
31
31
|
## Features
|
|
32
32
|
|
|
@@ -36,13 +36,15 @@ The Angular 21 package is compatible with Angular 21.x and was tested in a real
|
|
|
36
36
|
| Multi-select and single-select modes | ✅ |
|
|
37
37
|
| Search and filter | ✅ |
|
|
38
38
|
| Group by field | ✅ |
|
|
39
|
-
| Custom item templates (`<c-item>`) | ✅ |
|
|
39
|
+
| Custom item templates (`<c-item>`) with selected/ARIA context | ✅ |
|
|
40
40
|
| Custom badge templates (`<c-badge>`) | ✅ |
|
|
41
|
+
| Renderless Angular state helper for custom HTML | ✅ |
|
|
41
42
|
| Template-driven forms (`ngModel`) | ✅ |
|
|
42
43
|
| Reactive forms (`formControlName`) | ✅ |
|
|
43
44
|
| Lazy loading and remote-data hooks | ✅ |
|
|
44
45
|
| Theming via bundled CSS/SCSS | ✅ |
|
|
45
|
-
|
|
|
46
|
+
| Accessibility-focused keyboard navigation, focus states, and ARIA labels | ✅ |
|
|
47
|
+
| Matching `aria-selected` and `aria-checked` option state | ✅ |
|
|
46
48
|
| Primary selector `<angular-multiselect>` | ✅ |
|
|
47
49
|
| Legacy compatibility alias `<angular2-multiselect>` | ✅ |
|
|
48
50
|
| Versioned docs builds per Angular line | ✅ |
|
|
@@ -51,18 +53,21 @@ The Angular 21 package is compatible with Angular 21.x and was tested in a real
|
|
|
51
53
|
|
|
52
54
|
1. [Rename Note](#rename-note)
|
|
53
55
|
2. [Angular Version Compatibility](#angular-version-compatibility)
|
|
54
|
-
3. [
|
|
55
|
-
4. [
|
|
56
|
-
5. [
|
|
57
|
-
6. [
|
|
58
|
-
7. [
|
|
59
|
-
8. [
|
|
60
|
-
9. [
|
|
61
|
-
10. [
|
|
62
|
-
11. [
|
|
63
|
-
12. [
|
|
64
|
-
13. [
|
|
65
|
-
14. [
|
|
56
|
+
3. [StackBlitz Playground](#stackblitz-playground)
|
|
57
|
+
4. [Installation](#installation)
|
|
58
|
+
5. [Setup](#setup)
|
|
59
|
+
6. [Custom CSS and SCSS Themes](#custom-css-and-scss-themes)
|
|
60
|
+
7. [Basic Usage](#basic-usage)
|
|
61
|
+
8. [Official Angular 21 Test Matrix](#official-angular-21-test-matrix)
|
|
62
|
+
9. [Keyboard and ARIA Contract](#keyboard-and-aria-contract)
|
|
63
|
+
10. [Custom Templates](#custom-templates)
|
|
64
|
+
11. [Renderless State Helper](#renderless-state-helper)
|
|
65
|
+
12. [Forms Integration](#forms-integration)
|
|
66
|
+
13. [Lazy Loading and Remote Data](#lazy-loading-and-remote-data)
|
|
67
|
+
14. [Dialogs and Overflow Containers](#dialogs-and-overflow-containers)
|
|
68
|
+
15. [Events](#events)
|
|
69
|
+
16. [Run Locally](#run-locally)
|
|
70
|
+
17. [License](#license)
|
|
66
71
|
|
|
67
72
|
## Rename Note
|
|
68
73
|
|
|
@@ -79,7 +84,7 @@ Peer ranges are intentionally bounded to the tested Angular major. The Angular 2
|
|
|
79
84
|
|
|
80
85
|
| Package family | Framework family | Peer range | Tested release window | Demo link |
|
|
81
86
|
| :---: | :---: | :---: | :---: | :--- |
|
|
82
|
-
| **21.x** | **Angular 21 only** | **`>=21.0.0 <22.0.0`** | **21.
|
|
87
|
+
| **21.x** | **Angular 21 only** | **`>=21.0.0 <22.0.0`** | **21.2.0 -> 21.2.14** | [Angular 21 family docs](https://alexandro.net/docs/angular/multiselect/angular-21/) |
|
|
83
88
|
| **20.x** | **Angular 20 only** | **`>=20.0.0 <21.0.0`** | **20.0.1 -> 20.3.21** | [Angular 20 family docs](https://alexandro.net/docs/angular/multiselect/angular-20/) |
|
|
84
89
|
| **19.x** | **Angular 19 only** | **`>=19.0.0 <20.0.0`** | **19.0.1 -> 19.2.22** | [Angular 19 family docs](https://alexandro.net/docs/angular/multiselect/angular-19/) |
|
|
85
90
|
| **18.x** | **Angular 18 only** | **`>=18.0.0 <19.0.0`** | **18.0.1 -> 18.2.14** | [Angular 18 family docs](https://alexandro.net/docs/angular/multiselect/angular-18/) |
|
|
@@ -99,13 +104,44 @@ Peer ranges are intentionally bounded to the tested Angular major. The Angular 2
|
|
|
99
104
|
| **4.x** | **Angular 4 only** | **`>=4.0.0 <5.0.0`** | **4.0.2 -> 4.4.7** | [Angular 4 family docs](https://alexandro.net/docs/angular/multiselect/angular-4/) |
|
|
100
105
|
| **2.x** | **Angular 2 only** | **`>=2.0.0 <3.0.0`** | **compatible with 2.x; tested on 2.4.10** | [Angular 2 family docs](https://alexandro.net/docs/angular/multiselect/angular-2/) |
|
|
101
106
|
|
|
107
|
+
## StackBlitz Playground
|
|
108
|
+
|
|
109
|
+
The editable StackBlitz entry is one Angular 21 playground with isolated lazy routes. 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.
|
|
110
|
+
|
|
111
|
+
| Example | StackBlitz |
|
|
112
|
+
| :--- | :--- |
|
|
113
|
+
| Basic example | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fbasic) |
|
|
114
|
+
| Single selection | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fsingle-selection) |
|
|
115
|
+
| Search filter | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fsearch-filter) |
|
|
116
|
+
| Custom Search from API | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fcustom-search-api) |
|
|
117
|
+
| Search Filter By Property | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fsearch-filter-by-property) |
|
|
118
|
+
| Search and Add New Item | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fsearch-add-new-item) |
|
|
119
|
+
| Group By | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fgroup-by) |
|
|
120
|
+
| Templating | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Ftemplating) |
|
|
121
|
+
| Using in Forms | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Ftemplate-driven-forms) |
|
|
122
|
+
| Using in Reactive Forms | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Freactive-forms) |
|
|
123
|
+
| Virtual Scrolling | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fvirtual-scrolling) |
|
|
124
|
+
| Lazy Loading from API | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Flazy-loading-api) |
|
|
125
|
+
| Data from remote API | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fremote-data) |
|
|
126
|
+
| Using in List for loop | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Flist-loop) |
|
|
127
|
+
| Using Inside Dialog | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fdialog) |
|
|
128
|
+
| Multiple dropdowns | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fmultiple-dropdowns) |
|
|
129
|
+
| Load dynamic data | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fdynamic-data) |
|
|
130
|
+
| Methods | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fmethods) |
|
|
131
|
+
| Events | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fevents) |
|
|
132
|
+
| Disabled mode | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fdisabled) |
|
|
133
|
+
| Limit selection | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Flimit-selection) |
|
|
134
|
+
| Limit badges | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Flimit-badges) |
|
|
135
|
+
| Custom placeholder | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fcustom-placeholder) |
|
|
136
|
+
| Styling | [Open](https://stackblitz.com/github/alexandroit/stackline-angular-multiselect-angular-21?startScript=start&initialpath=%2Fstyling) |
|
|
137
|
+
|
|
102
138
|
## Installation
|
|
103
139
|
|
|
104
140
|
```bash
|
|
105
|
-
npm install @stackline/angular-multiselect-dropdown@21.
|
|
141
|
+
npm install @stackline/angular-multiselect-dropdown@21.2.0 --save-exact
|
|
106
142
|
```
|
|
107
143
|
|
|
108
|
-
Install `21.
|
|
144
|
+
Install `21.2.0` for Angular 21.x applications. This line keeps the tested Angular 21 behavior, makes `<angular-multiselect>` the documented standard selector, keeps `<angular2-multiselect>` only as a legacy compatibility alias, adds the accessibility-focused and keyboard/ARIA tested interaction contract, fixes responsive dropdown width handling, preserves selected objects during async refreshes, and keeps dropdown surfaces opaque in clipped containers.
|
|
109
145
|
|
|
110
146
|
## Setup
|
|
111
147
|
|
|
@@ -201,7 +237,7 @@ dropdownSettings = {
|
|
|
201
237
|
|
|
202
238
|
## Official Angular 21 Test Matrix
|
|
203
239
|
|
|
204
|
-
The published Angular 21 release was tested in a real Angular `21.2.14` application with `@stackline/angular-multiselect-dropdown@21.
|
|
240
|
+
The published Angular 21 release was tested in a real Angular `21.2.14` application with `@stackline/angular-multiselect-dropdown@21.2.0`. The docs now use the same examples from that test app, including the accessibility-focused keyboard, focus, and ARIA behavior, responsive dropdown width handling, opaque menu surfaces, and dialog-safe positioning added in this release line.
|
|
205
241
|
|
|
206
242
|
Switch between skins through the settings object:
|
|
207
243
|
|
|
@@ -236,6 +272,38 @@ The same twelve scenarios are validated for both `classic` and `material`:
|
|
|
236
272
|
| 11 | Local lazy loading | `{ lazyLoading: true, maxHeight: 120, badgeShowLimit: 3 }` |
|
|
237
273
|
| 12 | Item + chip template | `<c-badge>` and `<c-item>` custom templates |
|
|
238
274
|
|
|
275
|
+
## Keyboard and ARIA Contract
|
|
276
|
+
|
|
277
|
+
The Angular line follows the same combobox contract validated in the React 19.1.x work, but exposed through Angular settings:
|
|
278
|
+
|
|
279
|
+
```ts
|
|
280
|
+
dropdownSettings = {
|
|
281
|
+
text: 'Keyboard-tested countries',
|
|
282
|
+
enableSearchFilter: true,
|
|
283
|
+
searchAutofocus: false,
|
|
284
|
+
keyboard: {
|
|
285
|
+
space: true,
|
|
286
|
+
spaceOptionAction: 'toggle',
|
|
287
|
+
tab: true,
|
|
288
|
+
arrows: true,
|
|
289
|
+
escape: true,
|
|
290
|
+
backspaceRemovesLastWhenSearchEmpty: false,
|
|
291
|
+
deleteRemovesFocusedBadge: true
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Default behavior:
|
|
297
|
+
|
|
298
|
+
- Space on the trigger opens or closes the dropdown.
|
|
299
|
+
- Space on an option toggles that option and keeps focus on it.
|
|
300
|
+
- Search inputs type a normal space.
|
|
301
|
+
- Tab moves focus and never selects an option.
|
|
302
|
+
- Escape closes the list without clearing selected values.
|
|
303
|
+
- Empty-search Backspace does not remove selected values by default.
|
|
304
|
+
- Focused badge/remove buttons can remove intentionally with Backspace/Delete.
|
|
305
|
+
- Options expose matching `aria-selected` and `aria-checked` values.
|
|
306
|
+
|
|
239
307
|
## Custom Templates
|
|
240
308
|
|
|
241
309
|
```html
|
|
@@ -244,9 +312,15 @@ The same twelve scenarios are validated for both `classic` and `material`:
|
|
|
244
312
|
[(ngModel)]="selectedItems"
|
|
245
313
|
[settings]="dropdownSettings">
|
|
246
314
|
<c-item>
|
|
247
|
-
<ng-template
|
|
248
|
-
|
|
249
|
-
|
|
315
|
+
<ng-template
|
|
316
|
+
let-item="item"
|
|
317
|
+
let-label="label"
|
|
318
|
+
let-selected="selected"
|
|
319
|
+
let-ariaChecked="ariaChecked">
|
|
320
|
+
<span [attr.data-aria-checked]="ariaChecked">
|
|
321
|
+
{{ label }}
|
|
322
|
+
<strong *ngIf="selected">Selected</strong>
|
|
323
|
+
</span>
|
|
250
324
|
</ng-template>
|
|
251
325
|
</c-item>
|
|
252
326
|
</angular-multiselect>
|
|
@@ -254,6 +328,39 @@ The same twelve scenarios are validated for both `classic` and `material`:
|
|
|
254
328
|
|
|
255
329
|
`<angular2-multiselect>` remains available only as a legacy compatibility alias for applications migrating from the old outdated plugin. New code and all current examples should use `<angular-multiselect>`.
|
|
256
330
|
|
|
331
|
+
## Renderless State Helper
|
|
332
|
+
|
|
333
|
+
Use `AngularMultiselectState` when you want Stackline selection, filtering, item identity, object preservation, and ARIA state while owning all HTML yourself.
|
|
334
|
+
|
|
335
|
+
```ts
|
|
336
|
+
import {
|
|
337
|
+
AngularMultiselectState,
|
|
338
|
+
defineAngularMultiselectSettings
|
|
339
|
+
} from '@stackline/angular-multiselect-dropdown';
|
|
340
|
+
|
|
341
|
+
interface CountryOption {
|
|
342
|
+
id: number;
|
|
343
|
+
itemName: string;
|
|
344
|
+
region: string;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
state = new AngularMultiselectState<CountryOption>({
|
|
348
|
+
data: countries,
|
|
349
|
+
selectedItems: [countries[0]],
|
|
350
|
+
settings: defineAngularMultiselectSettings<CountryOption>({
|
|
351
|
+
primaryKey: 'id',
|
|
352
|
+
labelKey: 'itemName',
|
|
353
|
+
searchBy: ['itemName', 'region'],
|
|
354
|
+
ariaLabel: 'Headless country picker'
|
|
355
|
+
}),
|
|
356
|
+
onChange: (items) => {
|
|
357
|
+
selectedItems = items;
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
The docs include a `Headless + ARIA` route that binds the returned trigger, listbox, and option state into fully custom Angular HTML.
|
|
363
|
+
|
|
257
364
|
## Forms Integration
|
|
258
365
|
|
|
259
366
|
### Template-driven forms
|
|
@@ -313,7 +420,7 @@ settings = {
|
|
|
313
420
|
};
|
|
314
421
|
```
|
|
315
422
|
|
|
316
|
-
In `21.
|
|
423
|
+
In `21.2.0`, `tagToBody: true` renders the open panel outside clipping containers, keeps it aligned to the original trigger, keeps the menu surface opaque, recalculates position on scroll and resize, and cleans it up on close or destroy. `appendToBody: true` is also accepted as an alias for teams that prefer that name.
|
|
317
424
|
|
|
318
425
|
## Events
|
|
319
426
|
|