@progress/kendo-angular-dropdowns 21.4.1 → 22.0.0-develop.1
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/common/localization/messages.d.ts +1 -1
- package/dropdowntrees/checked-state/base-check.directive.d.ts +1 -1
- package/fesm2022/progress-kendo-angular-dropdowns.mjs +173 -173
- package/package.json +14 -22
- package/schematics/ngAdd/index.js +2 -2
- package/esm2022/autocomplete/autocomplete.component.mjs +0 -1687
- package/esm2022/autocomplete/autocomplete.module.mjs +0 -70
- package/esm2022/comboboxes/combobox-column/column-cell-template.directive.mjs +0 -42
- package/esm2022/comboboxes/combobox-column/column-header-template.directive.mjs +0 -40
- package/esm2022/comboboxes/combobox-column/combobox-column.component.mjs +0 -116
- package/esm2022/comboboxes/combobox-column/util.mjs +0 -60
- package/esm2022/comboboxes/combobox.component.mjs +0 -2149
- package/esm2022/comboboxes/combobox.module.mjs +0 -77
- package/esm2022/comboboxes/multicolumncombobox.component.mjs +0 -883
- package/esm2022/common/adaptive-renderer.component.mjs +0 -253
- package/esm2022/common/constants/error-messages.mjs +0 -61
- package/esm2022/common/data.service.mjs +0 -250
- package/esm2022/common/disabled-items/disabled-items.service.mjs +0 -47
- package/esm2022/common/disabled-items/item-disabled.mjs +0 -5
- package/esm2022/common/filter-input.directive.mjs +0 -39
- package/esm2022/common/filtering/filter-settings.mjs +0 -5
- package/esm2022/common/filtering/filter.directive.mjs +0 -136
- package/esm2022/common/filtering/filterable-component.mjs +0 -34
- package/esm2022/common/list-item.directive.mjs +0 -25
- package/esm2022/common/list.component.mjs +0 -968
- package/esm2022/common/localization/custom-messages.component.mjs +0 -96
- package/esm2022/common/localization/localized-messages.directive.mjs +0 -47
- package/esm2022/common/localization/messages.mjs +0 -77
- package/esm2022/common/models/checkboxes-settings.mjs +0 -15
- package/esm2022/common/models/direction.mjs +0 -5
- package/esm2022/common/models/fillmode.mjs +0 -5
- package/esm2022/common/models/list-type.mjs +0 -5
- package/esm2022/common/models/page-change-event.mjs +0 -5
- package/esm2022/common/models/popup-settings.mjs +0 -5
- package/esm2022/common/models/preventable-event.mjs +0 -25
- package/esm2022/common/models/remove-tag-event.mjs +0 -23
- package/esm2022/common/models/rounded.mjs +0 -5
- package/esm2022/common/models/size.mjs +0 -5
- package/esm2022/common/models/virtualization-settings.mjs +0 -24
- package/esm2022/common/navigation/navigation-action.mjs +0 -32
- package/esm2022/common/navigation/navigation.service.mjs +0 -188
- package/esm2022/common/searchbar.component.mjs +0 -386
- package/esm2022/common/selection/selectable.directive.mjs +0 -83
- package/esm2022/common/selection/selection.service.mjs +0 -166
- package/esm2022/common/shared-events.directive.mjs +0 -99
- package/esm2022/common/taglist.component.mjs +0 -295
- package/esm2022/common/templates/custom-item-template.directive.mjs +0 -48
- package/esm2022/common/templates/fixed-group-template.directive.mjs +0 -55
- package/esm2022/common/templates/footer-template.directive.mjs +0 -49
- package/esm2022/common/templates/group-tag-template.directive.mjs +0 -47
- package/esm2022/common/templates/group-template.directive.mjs +0 -55
- package/esm2022/common/templates/header-template.directive.mjs +0 -49
- package/esm2022/common/templates/item-template.directive.mjs +0 -48
- package/esm2022/common/templates/no-data-template.directive.mjs +0 -49
- package/esm2022/common/templates/tag-template.directive.mjs +0 -46
- package/esm2022/common/templates/value-template.directive.mjs +0 -50
- package/esm2022/common/util.mjs +0 -376
- package/esm2022/directives.mjs +0 -172
- package/esm2022/dropdownlist/dropdownlist.component.mjs +0 -1999
- package/esm2022/dropdownlist/dropdownlist.module.mjs +0 -79
- package/esm2022/dropdowns.module.mjs +0 -76
- package/esm2022/dropdowntrees/checked-state/base-check.directive.mjs +0 -76
- package/esm2022/dropdowntrees/checked-state/check-all.directive.mjs +0 -170
- package/esm2022/dropdowntrees/checked-state/check.directive.mjs +0 -168
- package/esm2022/dropdowntrees/checked-state/checkable-settings.mjs +0 -5
- package/esm2022/dropdowntrees/checked-state/checked-item.mjs +0 -5
- package/esm2022/dropdowntrees/data-binding/dropdowntree/flat-binding.directive.mjs +0 -69
- package/esm2022/dropdowntrees/data-binding/dropdowntree/hierarchy-binding.directive.mjs +0 -62
- package/esm2022/dropdowntrees/data-binding/multiselecttree/flat-binding.directive.mjs +0 -69
- package/esm2022/dropdowntrees/data-binding/multiselecttree/hierarchy-binding.directive.mjs +0 -62
- package/esm2022/dropdowntrees/dropdowntree.component.mjs +0 -1967
- package/esm2022/dropdowntrees/dropdowntrees.module.mjs +0 -79
- package/esm2022/dropdowntrees/expanded-state/expand.directive.mjs +0 -49
- package/esm2022/dropdowntrees/lookup/lookup.mjs +0 -5
- package/esm2022/dropdowntrees/lookup/lookup.service.mjs +0 -82
- package/esm2022/dropdowntrees/multiselecttree.component.mjs +0 -2359
- package/esm2022/dropdowntrees/summary-tag/summary-tag.directive.mjs +0 -70
- package/esm2022/dropdowntrees/templates/node-template.directive.mjs +0 -31
- package/esm2022/index.mjs +0 -55
- package/esm2022/multiselect/multiselect.component.mjs +0 -2380
- package/esm2022/multiselect/multiselect.module.mjs +0 -79
- package/esm2022/multiselect/summary-tag.directive.mjs +0 -68
- package/esm2022/package-metadata.mjs +0 -16
- package/esm2022/progress-kendo-angular-dropdowns.mjs +0 -8
|
@@ -1,2380 +0,0 @@
|
|
|
1
|
-
/**-----------------------------------------------------------------------------------------
|
|
2
|
-
* Copyright © 2026 Progress Software Corporation. All rights reserved.
|
|
3
|
-
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
-
*-------------------------------------------------------------------------------------------*/
|
|
5
|
-
import { isPresent, isArray, isObjectArray, resolveAllValues, selectedIndices, getter, isNumber, isUntouched, inDropDown, getSizeClass, getRoundedClass, getFillModeClass, animationDuration, isTruthy, setListBoxAriaLabelledBy, setActionSheetTitle } from '../common/util';
|
|
6
|
-
import { SearchBarComponent } from '../common/searchbar.component';
|
|
7
|
-
import { ViewChild, Renderer2, ViewContainerRef, Component, HostBinding, Input, ElementRef, TemplateRef, Output, EventEmitter, isDevMode, forwardRef, ContentChild, ChangeDetectorRef, KeyValueDiffers, NgZone, Injector } from '@angular/core';
|
|
8
|
-
import { Subscription, Subject, of, merge } from 'rxjs';
|
|
9
|
-
import { isChanged, isDocumentAvailable, KendoInput, hasObservers, anyChanged, SuffixTemplateDirective, PrefixTemplateDirective, isControlRequired, SeparatorComponent, ResizeSensorComponent, Keys, TemplateContextDirective, guid, normalizeKeys, parseCSSClassNames } from '@progress/kendo-angular-common';
|
|
10
|
-
import { AdaptiveService } from '@progress/kendo-angular-utils';
|
|
11
|
-
import { catchError, filter, map, take, tap } from 'rxjs/operators';
|
|
12
|
-
import { NG_VALUE_ACCESSOR, NgControl } from '@angular/forms';
|
|
13
|
-
import { validatePackage } from '@progress/kendo-licensing';
|
|
14
|
-
import { packageMetadata } from '../package-metadata';
|
|
15
|
-
import { SelectionService } from '../common/selection/selection.service';
|
|
16
|
-
import { NavigationService } from '../common/navigation/navigation.service';
|
|
17
|
-
import { NavigationAction } from '../common/navigation/navigation-action';
|
|
18
|
-
import { DisabledItemsService } from '../common/disabled-items/disabled-items.service';
|
|
19
|
-
import { ItemTemplateDirective } from '../common/templates/item-template.directive';
|
|
20
|
-
import { CustomItemTemplateDirective } from '../common/templates/custom-item-template.directive';
|
|
21
|
-
import { GroupTemplateDirective } from '../common/templates/group-template.directive';
|
|
22
|
-
import { FixedGroupTemplateDirective } from '../common/templates/fixed-group-template.directive';
|
|
23
|
-
import { HeaderTemplateDirective } from '../common/templates/header-template.directive';
|
|
24
|
-
import { FooterTemplateDirective } from '../common/templates/footer-template.directive';
|
|
25
|
-
import { TagTemplateDirective } from '../common/templates/tag-template.directive';
|
|
26
|
-
import { GroupTagTemplateDirective } from '../common/templates/group-tag-template.directive';
|
|
27
|
-
import { NoDataTemplateDirective } from '../common/templates/no-data-template.directive';
|
|
28
|
-
import { MultiselectMessages } from '../common/constants/error-messages';
|
|
29
|
-
import { PreventableEvent } from '../common/models/preventable-event';
|
|
30
|
-
import { RemoveTagEvent } from '../common/models/remove-tag-event';
|
|
31
|
-
import { LocalizationService, L10N_PREFIX } from '@progress/kendo-angular-l10n';
|
|
32
|
-
import { PopupService } from '@progress/kendo-angular-popup';
|
|
33
|
-
import { FilterableComponent } from '../common/filtering/filterable-component';
|
|
34
|
-
import { DataService } from '../common/data.service';
|
|
35
|
-
import { ListComponent } from '../common/list.component';
|
|
36
|
-
import { normalizeCheckboxesSettings } from '../common/models/checkboxes-settings';
|
|
37
|
-
import { normalizeVirtualizationSettings } from '../common/models/virtualization-settings';
|
|
38
|
-
import { xIcon } from '@progress/kendo-svg-icons';
|
|
39
|
-
import { AdaptiveRendererComponent } from '../common/adaptive-renderer.component';
|
|
40
|
-
import { TagListComponent } from '../common/taglist.component';
|
|
41
|
-
import { NgTemplateOutlet } from '@angular/common';
|
|
42
|
-
import { SharedDropDownEventsDirective } from '../common/shared-events.directive';
|
|
43
|
-
import { LocalizedMessagesDirective } from '../common/localization/localized-messages.directive';
|
|
44
|
-
import { IconWrapperComponent } from '@progress/kendo-angular-icons';
|
|
45
|
-
import { touchEnabled } from '@progress/kendo-common';
|
|
46
|
-
import * as i0 from "@angular/core";
|
|
47
|
-
import * as i1 from "@progress/kendo-angular-l10n";
|
|
48
|
-
import * as i2 from "@progress/kendo-angular-popup";
|
|
49
|
-
import * as i3 from "../common/data.service";
|
|
50
|
-
import * as i4 from "../common/selection/selection.service";
|
|
51
|
-
import * as i5 from "../common/navigation/navigation.service";
|
|
52
|
-
import * as i6 from "../common/disabled-items/disabled-items.service";
|
|
53
|
-
import * as i7 from "@progress/kendo-angular-utils";
|
|
54
|
-
const MULTISELECT_VALUE_ACCESSOR = {
|
|
55
|
-
multi: true,
|
|
56
|
-
provide: NG_VALUE_ACCESSOR,
|
|
57
|
-
useExisting: forwardRef(() => MultiSelectComponent)
|
|
58
|
-
};
|
|
59
|
-
const DEFAULT_SIZE = 'medium';
|
|
60
|
-
const DEFAULT_ROUNDED = 'medium';
|
|
61
|
-
const DEFAULT_FILL_MODE = 'solid';
|
|
62
|
-
/**
|
|
63
|
-
* Represents the [Kendo UI MultiSelect component for Angular]({% slug overview_multiselect %}).
|
|
64
|
-
*
|
|
65
|
-
* Use the `MultiSelectComponent` to show a dropdown list where users can select multiple items.
|
|
66
|
-
* [See example]({% slug overview_multiselect %}).
|
|
67
|
-
*
|
|
68
|
-
* @example
|
|
69
|
-
* ```typescript
|
|
70
|
-
* @Component({
|
|
71
|
-
* selector: 'my-app',
|
|
72
|
-
* template: `
|
|
73
|
-
* <kendo-multiselect
|
|
74
|
-
* [data]="listItems"
|
|
75
|
-
* textField="name"
|
|
76
|
-
* valueField="id"
|
|
77
|
-
* placeholder="Select items...">
|
|
78
|
-
* </kendo-multiselect>
|
|
79
|
-
* `
|
|
80
|
-
* })
|
|
81
|
-
* export class AppComponent {
|
|
82
|
-
* public listItems = [
|
|
83
|
-
* { id: 1, name: "Item 1" },
|
|
84
|
-
* { id: 2, name: "Item 2" },
|
|
85
|
-
* { id: 3, name: "Item 3" }
|
|
86
|
-
* ];
|
|
87
|
-
* }
|
|
88
|
-
* ```
|
|
89
|
-
* @remarks
|
|
90
|
-
* Supported children components are: {@link CustomMessagesComponent}.
|
|
91
|
-
*/
|
|
92
|
-
export class MultiSelectComponent {
|
|
93
|
-
wrapper;
|
|
94
|
-
localization;
|
|
95
|
-
popupService;
|
|
96
|
-
dataService;
|
|
97
|
-
selectionService;
|
|
98
|
-
navigationService;
|
|
99
|
-
disabledItemsService;
|
|
100
|
-
cdr;
|
|
101
|
-
differs;
|
|
102
|
-
renderer;
|
|
103
|
-
_zone;
|
|
104
|
-
injector;
|
|
105
|
-
hostElement;
|
|
106
|
-
adaptiveService;
|
|
107
|
-
/**
|
|
108
|
-
* @hidden
|
|
109
|
-
*/
|
|
110
|
-
animationDuration = animationDuration;
|
|
111
|
-
/**
|
|
112
|
-
* @hidden
|
|
113
|
-
*/
|
|
114
|
-
xIcon = xIcon;
|
|
115
|
-
listBoxId = `k-${guid()}`;
|
|
116
|
-
tagListId = `k-${guid()}`;
|
|
117
|
-
tagPrefix = "tag-" + guid();
|
|
118
|
-
optionPrefix = "option-" + guid();
|
|
119
|
-
popupRef;
|
|
120
|
-
text;
|
|
121
|
-
tags;
|
|
122
|
-
focusedTagIndex = undefined;
|
|
123
|
-
/**
|
|
124
|
-
* @hidden
|
|
125
|
-
*/
|
|
126
|
-
adaptiveRendererComponent;
|
|
127
|
-
/**
|
|
128
|
-
* @hidden
|
|
129
|
-
*/
|
|
130
|
-
get actionSheet() {
|
|
131
|
-
return this.adaptiveRendererComponent?.actionSheet;
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* @hidden
|
|
135
|
-
*/
|
|
136
|
-
get actionSheetSearchBar() {
|
|
137
|
-
return this.adaptiveRendererComponent?.actionSheetSearchBar;
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* @hidden
|
|
141
|
-
*/
|
|
142
|
-
get ariaControls() {
|
|
143
|
-
return this.isOpen ? this.listBoxId : undefined;
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* @hidden
|
|
147
|
-
*/
|
|
148
|
-
get isControlRequired() {
|
|
149
|
-
return isControlRequired(this.formControl);
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* @hidden
|
|
153
|
-
*/
|
|
154
|
-
get formControl() {
|
|
155
|
-
const ngControl = this.injector.get(NgControl, null);
|
|
156
|
-
return ngControl?.control || null;
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Focuses a specific item in the MultiSelect based on the provided index.
|
|
160
|
-
* Sets the index to `-1` to focus the custom item if available.
|
|
161
|
-
* Pass `null` or an invalid index to remove focus.
|
|
162
|
-
*/
|
|
163
|
-
focusItemAt(index) {
|
|
164
|
-
const minIndex = this.allowCustom ? -1 : 0;
|
|
165
|
-
const isInRange = minIndex <= 0 && index < this.data.length;
|
|
166
|
-
if (isPresent(index) && isInRange && !this.disabledItemsService.isIndexDisabled(index)) {
|
|
167
|
-
this.selectionService.focus(index);
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
this.selectionService.focus(null);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Focuses the MultiSelect input element.
|
|
175
|
-
*/
|
|
176
|
-
focus() {
|
|
177
|
-
if (!this.disabled) {
|
|
178
|
-
this.searchbar.focus();
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* @hidden
|
|
183
|
-
*/
|
|
184
|
-
handleInputFocus() {
|
|
185
|
-
this.handleFocus();
|
|
186
|
-
if (hasObservers(this.inputFocus)) {
|
|
187
|
-
this._zone.run(() => {
|
|
188
|
-
this.inputFocus.emit();
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Removes focus from the MultiSelect input element.
|
|
194
|
-
*/
|
|
195
|
-
blur() {
|
|
196
|
-
if (!this.disabled) {
|
|
197
|
-
this.searchbar.blur();
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* @hidden
|
|
202
|
-
*/
|
|
203
|
-
handleFocus() {
|
|
204
|
-
this._zone.run(() => {
|
|
205
|
-
if (!this.isFocused && hasObservers(this.onFocus)) {
|
|
206
|
-
this.onFocus.emit();
|
|
207
|
-
}
|
|
208
|
-
this.isFocused = true;
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* @hidden
|
|
213
|
-
*/
|
|
214
|
-
handleBlur() {
|
|
215
|
-
if (!this.isActionSheetExpanded) {
|
|
216
|
-
this.blurComponent();
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* @hidden
|
|
221
|
-
*/
|
|
222
|
-
handleInputBlur() {
|
|
223
|
-
if (!this.isActionSheetExpanded) {
|
|
224
|
-
if (!this.isFocused) {
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
if (hasObservers(this.inputBlur) ||
|
|
228
|
-
hasObservers(this.filterChange) ||
|
|
229
|
-
hasObservers(this.close) ||
|
|
230
|
-
isUntouched(this.wrapper.nativeElement) ||
|
|
231
|
-
this.formControl?.updateOn === 'blur') {
|
|
232
|
-
this._zone.run(() => {
|
|
233
|
-
this.closePopup();
|
|
234
|
-
if (!(this.isOpen && this.allowCustom)) {
|
|
235
|
-
this.clearFilter();
|
|
236
|
-
}
|
|
237
|
-
this.inputBlur.emit();
|
|
238
|
-
this.onTouchedCallback();
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
else {
|
|
242
|
-
if (!this.allowCustom) {
|
|
243
|
-
this.clearFilter();
|
|
244
|
-
}
|
|
245
|
-
this.closePopup();
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* @hidden
|
|
251
|
-
*/
|
|
252
|
-
onPointerDown(event) {
|
|
253
|
-
event.preventDefault();
|
|
254
|
-
}
|
|
255
|
-
/**
|
|
256
|
-
* @hidden
|
|
257
|
-
*/
|
|
258
|
-
onResize() {
|
|
259
|
-
const currentWindowSize = this.adaptiveService.size;
|
|
260
|
-
if (this.isAdaptiveModeEnabled && this.windowSize !== currentWindowSize) {
|
|
261
|
-
if (this.isOpen) {
|
|
262
|
-
this.togglePopup(false);
|
|
263
|
-
}
|
|
264
|
-
this.windowSize = currentWindowSize;
|
|
265
|
-
this.cdr.detectChanges();
|
|
266
|
-
}
|
|
267
|
-
if (this.isOpen && !this.isActionSheetExpanded) {
|
|
268
|
-
const popupWrapper = this.popupRef.popupElement;
|
|
269
|
-
const { min, max } = this.width;
|
|
270
|
-
popupWrapper.style.minWidth = min;
|
|
271
|
-
popupWrapper.style.width = max;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
get appendTo() {
|
|
275
|
-
const { appendTo } = this.popupSettings;
|
|
276
|
-
if (!appendTo || appendTo === 'root') {
|
|
277
|
-
return undefined;
|
|
278
|
-
}
|
|
279
|
-
return appendTo === 'component' ? this.container : appendTo;
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* Shows or hides the current group sticky header when using grouped data.
|
|
283
|
-
* By default the sticky header is displayed ([see example]({% slug grouping_autocomplete %}#toc-sticky-header)).
|
|
284
|
-
*/
|
|
285
|
-
showStickyHeader = true;
|
|
286
|
-
/**
|
|
287
|
-
* @hidden
|
|
288
|
-
*/
|
|
289
|
-
focusableId = `k-${guid()}`;
|
|
290
|
-
/**
|
|
291
|
-
* Controls whether the options list closes after item selection finishes ([see example]({% slug openstate_multiselect %}#toc-keeping-the-options-list-open-while-on-focus)).
|
|
292
|
-
* Set to `false` to keep the list open while the component has focus.
|
|
293
|
-
*
|
|
294
|
-
* @default true
|
|
295
|
-
*/
|
|
296
|
-
autoClose = true;
|
|
297
|
-
/**
|
|
298
|
-
* Controls the loading state of the MultiSelect.
|
|
299
|
-
* Set to `true` to display the loading indicator.
|
|
300
|
-
*/
|
|
301
|
-
loading;
|
|
302
|
-
/**
|
|
303
|
-
* Sets the data source for the MultiSelect.
|
|
304
|
-
* Provide the data as an array of items.
|
|
305
|
-
*/
|
|
306
|
-
set data(data) {
|
|
307
|
-
this.dataService.data = data || [];
|
|
308
|
-
if (this.virtual) {
|
|
309
|
-
this.virtual.skip = 0;
|
|
310
|
-
}
|
|
311
|
-
if (this.initialized) {
|
|
312
|
-
this.setState(this.value);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
get data() {
|
|
316
|
-
const virtual = this.virtual;
|
|
317
|
-
if (virtual) {
|
|
318
|
-
const start = virtual.skip || 0;
|
|
319
|
-
const end = start + virtual.pageSize;
|
|
320
|
-
//Use length instead of itemsCount because of grouping
|
|
321
|
-
virtual.total = this.dataService.data.length;
|
|
322
|
-
return this.dataService.data.slice(start, end);
|
|
323
|
-
}
|
|
324
|
-
return this.dataService.data;
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Sets the selected values of the MultiSelect.
|
|
328
|
-
* Accepts primitive values (strings, numbers) or complex objects.
|
|
329
|
-
* Use the `valuePrimitive` property to define the value type.
|
|
330
|
-
* > The component ignores selected values that don't exist in the data source.
|
|
331
|
-
*/
|
|
332
|
-
set value(values) {
|
|
333
|
-
this._value = values ? values : [];
|
|
334
|
-
if (!this.differ && this.value) {
|
|
335
|
-
this.differ = this.differs.find(this.value).create();
|
|
336
|
-
}
|
|
337
|
-
this.valueChangeDetected = true;
|
|
338
|
-
if (this.initialized) {
|
|
339
|
-
this.setState(this.value);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
get value() {
|
|
343
|
-
return this._value;
|
|
344
|
-
}
|
|
345
|
-
/**
|
|
346
|
-
* Sets the field name that contains the item value in the data objects.
|
|
347
|
-
* Skip this property when your data contains only primitive values.
|
|
348
|
-
* Supports nested property paths like `category.id`.
|
|
349
|
-
*/
|
|
350
|
-
valueField;
|
|
351
|
-
/**
|
|
352
|
-
* Sets the field name that contains the item text in the data objects.
|
|
353
|
-
* Skip this property when your data contains only primitive values.
|
|
354
|
-
* Supports nested property paths like `category.name`.
|
|
355
|
-
*/
|
|
356
|
-
textField;
|
|
357
|
-
/**
|
|
358
|
-
* Sets the [`tabindex`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) attribute of the component.
|
|
359
|
-
*
|
|
360
|
-
* @default 0
|
|
361
|
-
*/
|
|
362
|
-
tabindex = 0;
|
|
363
|
-
/**
|
|
364
|
-
* @hidden
|
|
365
|
-
*/
|
|
366
|
-
set tabIndex(tabIndex) {
|
|
367
|
-
this.tabindex = tabIndex;
|
|
368
|
-
}
|
|
369
|
-
get tabIndex() {
|
|
370
|
-
return this.tabindex;
|
|
371
|
-
}
|
|
372
|
-
/**
|
|
373
|
-
* Sets the size of the component.
|
|
374
|
-
*
|
|
375
|
-
* @default "medium"
|
|
376
|
-
*/
|
|
377
|
-
set size(size) {
|
|
378
|
-
const newSize = size ? size : DEFAULT_SIZE;
|
|
379
|
-
this.renderer.removeClass(this.wrapper.nativeElement, getSizeClass('input', this.size));
|
|
380
|
-
if (size !== 'none') {
|
|
381
|
-
this.renderer.addClass(this.wrapper.nativeElement, getSizeClass('input', newSize));
|
|
382
|
-
}
|
|
383
|
-
this._size = newSize;
|
|
384
|
-
}
|
|
385
|
-
get size() {
|
|
386
|
-
return this._size;
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* Sets the border radius of the component.
|
|
390
|
-
*
|
|
391
|
-
* @default "medium"
|
|
392
|
-
*/
|
|
393
|
-
set rounded(rounded) {
|
|
394
|
-
const newRounded = rounded ? rounded : DEFAULT_ROUNDED;
|
|
395
|
-
this.renderer.removeClass(this.wrapper.nativeElement, getRoundedClass(this.rounded));
|
|
396
|
-
if (rounded !== 'none') {
|
|
397
|
-
this.renderer.addClass(this.wrapper.nativeElement, getRoundedClass(newRounded));
|
|
398
|
-
}
|
|
399
|
-
this._rounded = newRounded;
|
|
400
|
-
}
|
|
401
|
-
get rounded() {
|
|
402
|
-
return this._rounded;
|
|
403
|
-
}
|
|
404
|
-
/**
|
|
405
|
-
* Sets the fill mode of the component.
|
|
406
|
-
*
|
|
407
|
-
* @default "solid"
|
|
408
|
-
*/
|
|
409
|
-
set fillMode(fillMode) {
|
|
410
|
-
const newFillMode = fillMode ? fillMode : DEFAULT_FILL_MODE;
|
|
411
|
-
this.renderer.removeClass(this.wrapper.nativeElement, getFillModeClass('input', this.fillMode));
|
|
412
|
-
if (fillMode !== 'none') {
|
|
413
|
-
this.renderer.addClass(this.wrapper.nativeElement, getFillModeClass('input', newFillMode));
|
|
414
|
-
}
|
|
415
|
-
this._fillMode = newFillMode;
|
|
416
|
-
}
|
|
417
|
-
get fillMode() {
|
|
418
|
-
return this._fillMode;
|
|
419
|
-
}
|
|
420
|
-
/**
|
|
421
|
-
* Sets the placeholder text for the MultiSelect input.
|
|
422
|
-
* When the values are selected, it disappears.
|
|
423
|
-
*/
|
|
424
|
-
set placeholder(text) {
|
|
425
|
-
this._placeholder = text || '';
|
|
426
|
-
}
|
|
427
|
-
get placeholder() {
|
|
428
|
-
return this.selectedDataItems.length ? '' : this._placeholder;
|
|
429
|
-
}
|
|
430
|
-
/**
|
|
431
|
-
* Controls the adaptive mode behavior of the component.
|
|
432
|
-
* Set to `auto` to enable adaptive rendering on small screens.
|
|
433
|
-
*
|
|
434
|
-
* @default "none"
|
|
435
|
-
*/
|
|
436
|
-
adaptiveMode = 'none';
|
|
437
|
-
/**
|
|
438
|
-
* Sets the title text for the ActionSheet in adaptive mode.
|
|
439
|
-
* Uses the component's label text by default.
|
|
440
|
-
*/
|
|
441
|
-
adaptiveTitle = '';
|
|
442
|
-
/**
|
|
443
|
-
* Sets the subtitle text for the ActionSheet in adaptive mode.
|
|
444
|
-
* No subtitle appears by default.
|
|
445
|
-
*/
|
|
446
|
-
adaptiveSubtitle;
|
|
447
|
-
/**
|
|
448
|
-
* @hidden
|
|
449
|
-
*/
|
|
450
|
-
get isAdaptiveModeEnabled() {
|
|
451
|
-
return this.adaptiveMode === 'auto';
|
|
452
|
-
}
|
|
453
|
-
/**
|
|
454
|
-
* Controls the disabled state of the component.
|
|
455
|
-
* When true, sets the component to disabled.
|
|
456
|
-
* To learn how to disable the component in reactive forms, refer to the article on [Forms Support](slug:formssupport_multiselect#toc-managing-the-multiselect-disabled-state-in-reactive-forms).
|
|
457
|
-
*
|
|
458
|
-
* @default false
|
|
459
|
-
*/
|
|
460
|
-
disabled = false;
|
|
461
|
-
/**
|
|
462
|
-
* Determines wether the item will be disabled. The function is executed for each data item.
|
|
463
|
-
* The function receives the item as an argument and should return `true` if the item is disabled.
|
|
464
|
-
*/
|
|
465
|
-
set itemDisabled(fn) {
|
|
466
|
-
if (typeof fn !== 'function') {
|
|
467
|
-
throw new Error(`itemDisabled must be a function, but received ${JSON.stringify(fn)}.`);
|
|
468
|
-
}
|
|
469
|
-
this.disabledItemsService.itemDisabled = fn;
|
|
470
|
-
}
|
|
471
|
-
/**
|
|
472
|
-
* Controls whether checkboxes appear before each item in the popup list.
|
|
473
|
-
* Pass `true` to enable checkboxes or an object to configure checkbox settings.
|
|
474
|
-
*
|
|
475
|
-
* @default false
|
|
476
|
-
*/
|
|
477
|
-
set checkboxes(settings) {
|
|
478
|
-
this._checkboxes = normalizeCheckboxesSettings(settings);
|
|
479
|
-
}
|
|
480
|
-
get checkboxes() {
|
|
481
|
-
return this._checkboxes;
|
|
482
|
-
}
|
|
483
|
-
/**
|
|
484
|
-
* Controls the read-only state of the component.
|
|
485
|
-
* When true, the component does not allow user input or selection changes.
|
|
486
|
-
*
|
|
487
|
-
* @default false
|
|
488
|
-
*/
|
|
489
|
-
readonly = false;
|
|
490
|
-
/**
|
|
491
|
-
* Enables the filtering functionality of the MultiSelect.
|
|
492
|
-
* Set to `true` to allow users to filter the data by typing.
|
|
493
|
-
*
|
|
494
|
-
* @default false
|
|
495
|
-
*/
|
|
496
|
-
filterable = false;
|
|
497
|
-
/**
|
|
498
|
-
* Enables virtualization to improve performance with large datasets.
|
|
499
|
-
* Pass `true` for default settings or an object to configure virtualization.
|
|
500
|
-
*/
|
|
501
|
-
set virtual(settings) {
|
|
502
|
-
this._virtualSettings = normalizeVirtualizationSettings(settings);
|
|
503
|
-
}
|
|
504
|
-
get virtual() {
|
|
505
|
-
return this._virtualSettings;
|
|
506
|
-
}
|
|
507
|
-
/**
|
|
508
|
-
* Configures the popup appearance and behavior.
|
|
509
|
-
* Set properties like `animate`, `width`, `height`, `popupClass`, and `appendTo`.
|
|
510
|
-
*/
|
|
511
|
-
set popupSettings(settings) {
|
|
512
|
-
this._popupSettings = Object.assign({ animate: true }, settings);
|
|
513
|
-
}
|
|
514
|
-
get popupSettings() {
|
|
515
|
-
return this._popupSettings;
|
|
516
|
-
}
|
|
517
|
-
/**
|
|
518
|
-
* Sets the height of the options list in the popup.
|
|
519
|
-
* This affects only the list height, not the entire popup container.
|
|
520
|
-
*
|
|
521
|
-
* @default 200
|
|
522
|
-
*/
|
|
523
|
-
set listHeight(_listHeight) {
|
|
524
|
-
this._listHeight = _listHeight;
|
|
525
|
-
}
|
|
526
|
-
get listHeight() {
|
|
527
|
-
if (this.isAdaptive) {
|
|
528
|
-
return;
|
|
529
|
-
}
|
|
530
|
-
return this._listHeight;
|
|
531
|
-
}
|
|
532
|
-
_listHeight = 200;
|
|
533
|
-
/**
|
|
534
|
-
* Controls the type of selected values.
|
|
535
|
-
* Set to `true` for primitive values or `false` for object references.
|
|
536
|
-
* When undefined, the component determines the type based on `valueField`.
|
|
537
|
-
*/
|
|
538
|
-
set valuePrimitive(isPrimitive) {
|
|
539
|
-
this._valuePrimitive = isPrimitive;
|
|
540
|
-
}
|
|
541
|
-
get valuePrimitive() {
|
|
542
|
-
if (!isPresent(this._valuePrimitive)) {
|
|
543
|
-
return !isPresent(this.valueField);
|
|
544
|
-
}
|
|
545
|
-
return this._valuePrimitive;
|
|
546
|
-
}
|
|
547
|
-
/**
|
|
548
|
-
* Controls whether a clear button appears when items are selected.
|
|
549
|
-
* Set to `true` to show the button that clears all selections.
|
|
550
|
-
*
|
|
551
|
-
* @default true
|
|
552
|
-
*/
|
|
553
|
-
clearButton = true;
|
|
554
|
-
/**
|
|
555
|
-
* Sets a function that transforms selected data items into display tags.
|
|
556
|
-
* Use this to customize how selected items appear as tags.
|
|
557
|
-
*
|
|
558
|
-
* @default (tags) => tags || []
|
|
559
|
-
*/
|
|
560
|
-
tagMapper = (tags) => tags || [];
|
|
561
|
-
/**
|
|
562
|
-
* Allows users to add custom values not present in the data source.
|
|
563
|
-
* Set to `true` to enable custom value input.
|
|
564
|
-
* This feature is not available in adaptive mode.
|
|
565
|
-
*
|
|
566
|
-
* @default false
|
|
567
|
-
*/
|
|
568
|
-
allowCustom = false;
|
|
569
|
-
/**
|
|
570
|
-
* Sets a function that normalizes custom user input into data items.
|
|
571
|
-
* Use this when your data items differ from simple strings.
|
|
572
|
-
*/
|
|
573
|
-
valueNormalizer = (text) => text.pipe(map((userInput) => {
|
|
574
|
-
const comparer = (item) => typeof item === 'string' && userInput.toLowerCase() === item.toLowerCase();
|
|
575
|
-
const matchingValue = this.value.find(comparer);
|
|
576
|
-
if (matchingValue) {
|
|
577
|
-
return matchingValue;
|
|
578
|
-
}
|
|
579
|
-
const matchingItem = this.dataService.find(comparer);
|
|
580
|
-
return matchingItem ? matchingItem : userInput;
|
|
581
|
-
}));
|
|
582
|
-
/**
|
|
583
|
-
* Sets HTML attributes for the inner input element.
|
|
584
|
-
* You cannot change attributes essential for component functionality.
|
|
585
|
-
*/
|
|
586
|
-
inputAttributes;
|
|
587
|
-
/**
|
|
588
|
-
* Fires when the user types in the input field.
|
|
589
|
-
* Use this event to filter the data source based on user input.
|
|
590
|
-
*/
|
|
591
|
-
filterChange = new EventEmitter();
|
|
592
|
-
/**
|
|
593
|
-
* Fires when the value changes through user interaction or the Clear button.
|
|
594
|
-
* This event does not fire when you change the value programmatically.
|
|
595
|
-
*/
|
|
596
|
-
valueChange = new EventEmitter();
|
|
597
|
-
/**
|
|
598
|
-
* Fires before the popup opens.
|
|
599
|
-
* You can prevent the popup from opening by calling `preventDefault()` on the event.
|
|
600
|
-
*/
|
|
601
|
-
open = new EventEmitter();
|
|
602
|
-
/**
|
|
603
|
-
* Fires after the popup opens completely.
|
|
604
|
-
*/
|
|
605
|
-
opened = new EventEmitter();
|
|
606
|
-
/**
|
|
607
|
-
* Fires before the popup closes.
|
|
608
|
-
* You can prevent the popup from closing by calling `preventDefault()` on the event.
|
|
609
|
-
*/
|
|
610
|
-
close = new EventEmitter();
|
|
611
|
-
/**
|
|
612
|
-
* Fires after the popup closes completely.
|
|
613
|
-
*/
|
|
614
|
-
closed = new EventEmitter();
|
|
615
|
-
/**
|
|
616
|
-
* Fires when the user focuses the MultiSelect component.
|
|
617
|
-
*/
|
|
618
|
-
onFocus = new EventEmitter();
|
|
619
|
-
/**
|
|
620
|
-
* Fires when the MultiSelect component loses focus.
|
|
621
|
-
*/
|
|
622
|
-
onBlur = new EventEmitter();
|
|
623
|
-
/**
|
|
624
|
-
* Fires when the user focuses the input element inside the MultiSelect.
|
|
625
|
-
*/
|
|
626
|
-
inputFocus = new EventEmitter();
|
|
627
|
-
/**
|
|
628
|
-
* Fires when the input element inside the MultiSelect loses focus.
|
|
629
|
-
*/
|
|
630
|
-
inputBlur = new EventEmitter();
|
|
631
|
-
/**
|
|
632
|
-
* Fires before a tag gets removed from the selection.
|
|
633
|
-
* You can prevent tag removal by calling `preventDefault()` on the event.
|
|
634
|
-
*/
|
|
635
|
-
removeTag = new EventEmitter();
|
|
636
|
-
container;
|
|
637
|
-
searchbar;
|
|
638
|
-
tagList;
|
|
639
|
-
popupTemplate;
|
|
640
|
-
optionsList;
|
|
641
|
-
template;
|
|
642
|
-
customItemTemplate;
|
|
643
|
-
groupTemplate;
|
|
644
|
-
fixedGroupTemplate;
|
|
645
|
-
headerTemplate;
|
|
646
|
-
footerTemplate;
|
|
647
|
-
tagTemplate;
|
|
648
|
-
groupTagTemplate;
|
|
649
|
-
noDataTemplate;
|
|
650
|
-
/**
|
|
651
|
-
* @hidden
|
|
652
|
-
*/
|
|
653
|
-
suffixTemplate;
|
|
654
|
-
/**
|
|
655
|
-
* @hidden
|
|
656
|
-
*/
|
|
657
|
-
prefixTemplate;
|
|
658
|
-
hostClasses = true;
|
|
659
|
-
get dir() {
|
|
660
|
-
return this.direction;
|
|
661
|
-
}
|
|
662
|
-
get disabledClass() {
|
|
663
|
-
return this.disabled;
|
|
664
|
-
}
|
|
665
|
-
get isLoading() {
|
|
666
|
-
return this.loading;
|
|
667
|
-
}
|
|
668
|
-
/**
|
|
669
|
-
* @hidden
|
|
670
|
-
*/
|
|
671
|
-
windowSize = 'large';
|
|
672
|
-
/**
|
|
673
|
-
* @hidden
|
|
674
|
-
*/
|
|
675
|
-
get isActionSheetExpanded() {
|
|
676
|
-
return this.actionSheet?.expanded;
|
|
677
|
-
}
|
|
678
|
-
/**
|
|
679
|
-
* @hidden
|
|
680
|
-
*/
|
|
681
|
-
get isAdaptive() {
|
|
682
|
-
return this.isAdaptiveModeEnabled && this.windowSize !== 'large';
|
|
683
|
-
}
|
|
684
|
-
/**
|
|
685
|
-
* @hidden
|
|
686
|
-
*/
|
|
687
|
-
applyValue() {
|
|
688
|
-
if (!this.isActionSheetExpanded) {
|
|
689
|
-
return;
|
|
690
|
-
}
|
|
691
|
-
const isValueChanged = !(this.value.every(i => this._valueHolder.find(item => i === item)) && this._valueHolder.length === this.value.length);
|
|
692
|
-
if (isValueChanged) {
|
|
693
|
-
this.value = this._valueHolder;
|
|
694
|
-
this._valueHolder = [];
|
|
695
|
-
this.emitValueChange();
|
|
696
|
-
}
|
|
697
|
-
this.clearFilter();
|
|
698
|
-
this.togglePopup(false);
|
|
699
|
-
if (this.allowCustom && this.isCustomValueSelected) {
|
|
700
|
-
this.isCustomValueSelected = false;
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
disabledIndices;
|
|
704
|
-
initialized = false;
|
|
705
|
-
_size = 'medium';
|
|
706
|
-
_rounded = 'medium';
|
|
707
|
-
_fillMode = 'solid';
|
|
708
|
-
_valueHolder = [];
|
|
709
|
-
isCustomValueSelected = false;
|
|
710
|
-
constructor(wrapper, localization, popupService, dataService, selectionService, navigationService, disabledItemsService, cdr, differs, renderer, _zone, injector, hostElement, adaptiveService) {
|
|
711
|
-
this.wrapper = wrapper;
|
|
712
|
-
this.localization = localization;
|
|
713
|
-
this.popupService = popupService;
|
|
714
|
-
this.dataService = dataService;
|
|
715
|
-
this.selectionService = selectionService;
|
|
716
|
-
this.navigationService = navigationService;
|
|
717
|
-
this.disabledItemsService = disabledItemsService;
|
|
718
|
-
this.cdr = cdr;
|
|
719
|
-
this.differs = differs;
|
|
720
|
-
this.renderer = renderer;
|
|
721
|
-
this._zone = _zone;
|
|
722
|
-
this.injector = injector;
|
|
723
|
-
this.hostElement = hostElement;
|
|
724
|
-
this.adaptiveService = adaptiveService;
|
|
725
|
-
validatePackage(packageMetadata);
|
|
726
|
-
this.popupPointerDownHandler = this.onPointerDown.bind(this);
|
|
727
|
-
this.data = [];
|
|
728
|
-
this.direction = this.localization.rtl ? 'rtl' : 'ltr';
|
|
729
|
-
this.subscribeEvents();
|
|
730
|
-
this.subscribeTouchEvents();
|
|
731
|
-
}
|
|
732
|
-
get listContainerClasses() {
|
|
733
|
-
const containerClasses = ['k-list-container', 'k-multiselect-popup'];
|
|
734
|
-
if (!this.popupSettings.popupClass) {
|
|
735
|
-
return containerClasses;
|
|
736
|
-
}
|
|
737
|
-
const parsedPopupClasses = parseCSSClassNames(this.popupSettings.popupClass);
|
|
738
|
-
if (parsedPopupClasses?.length) {
|
|
739
|
-
containerClasses.push(...parsedPopupClasses);
|
|
740
|
-
}
|
|
741
|
-
return containerClasses;
|
|
742
|
-
}
|
|
743
|
-
/**
|
|
744
|
-
* @hidden
|
|
745
|
-
*/
|
|
746
|
-
get customItemSizeClass() {
|
|
747
|
-
const currentSize = this.isAdaptive ? 'large' : this.size;
|
|
748
|
-
return `${currentSize ? getSizeClass('list', currentSize) : ''}`;
|
|
749
|
-
}
|
|
750
|
-
get width() {
|
|
751
|
-
let wrapperOffsetWidth = 0;
|
|
752
|
-
if (isDocumentAvailable()) {
|
|
753
|
-
wrapperOffsetWidth = this.wrapper.nativeElement.offsetWidth;
|
|
754
|
-
}
|
|
755
|
-
const width = this.popupSettings.width || wrapperOffsetWidth;
|
|
756
|
-
const minWidth = isNaN(wrapperOffsetWidth) ? wrapperOffsetWidth : `${wrapperOffsetWidth}px`;
|
|
757
|
-
const maxWidth = isNaN(width) ? width : `${width}px`;
|
|
758
|
-
return { min: minWidth, max: maxWidth };
|
|
759
|
-
}
|
|
760
|
-
get height() {
|
|
761
|
-
const popupHeight = this.popupSettings.height;
|
|
762
|
-
return isPresent(popupHeight) ? `${popupHeight}px` : 'auto';
|
|
763
|
-
}
|
|
764
|
-
get activeDescendant() {
|
|
765
|
-
const focusedTagIndex = this.focusedTagIndex;
|
|
766
|
-
const focusedListIndex = this.selectionService.focused;
|
|
767
|
-
let prefix;
|
|
768
|
-
let focusedIndex;
|
|
769
|
-
if (isPresent(focusedTagIndex) && !this.isOpen) {
|
|
770
|
-
focusedIndex = focusedTagIndex;
|
|
771
|
-
prefix = this.tagPrefix;
|
|
772
|
-
}
|
|
773
|
-
else if (isPresent(focusedListIndex) && focusedListIndex !== -1 && this.isOpen) {
|
|
774
|
-
focusedIndex = focusedListIndex;
|
|
775
|
-
prefix = this.optionPrefix;
|
|
776
|
-
}
|
|
777
|
-
else {
|
|
778
|
-
return null;
|
|
779
|
-
}
|
|
780
|
-
return prefix + "-" + focusedIndex;
|
|
781
|
-
}
|
|
782
|
-
get clearButtonVisibility() {
|
|
783
|
-
if (touchEnabled) {
|
|
784
|
-
return 'visible';
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
/**
|
|
788
|
-
* @hidden
|
|
789
|
-
*/
|
|
790
|
-
verifySettings() {
|
|
791
|
-
if (!isDevMode() || this.value.length === 0) {
|
|
792
|
-
return;
|
|
793
|
-
}
|
|
794
|
-
if (!isArray(this.value)) {
|
|
795
|
-
throw new Error(MultiselectMessages.array);
|
|
796
|
-
}
|
|
797
|
-
if (this.valuePrimitive === true && isObjectArray(this.value)) {
|
|
798
|
-
throw new Error(MultiselectMessages.primitive);
|
|
799
|
-
}
|
|
800
|
-
if (this.valuePrimitive === false && !isObjectArray(this.value)) {
|
|
801
|
-
throw new Error(MultiselectMessages.object);
|
|
802
|
-
}
|
|
803
|
-
const valueOrText = !isPresent(this.valueField) !== !isPresent(this.textField);
|
|
804
|
-
if (valueOrText) {
|
|
805
|
-
throw new Error(MultiselectMessages.textAndValue);
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
/**
|
|
809
|
-
* @hidden
|
|
810
|
-
*/
|
|
811
|
-
change(event) {
|
|
812
|
-
if (event.isMultipleSelection) {
|
|
813
|
-
// Existing items.
|
|
814
|
-
if (isPresent(event.added) && event.added.length > 0) {
|
|
815
|
-
event.added.forEach((itemIndex) => {
|
|
816
|
-
const dataItem = this.dataService.itemAt(itemIndex);
|
|
817
|
-
const newItem = (this.valuePrimitive && isPresent(dataItem) && isPresent(getter(dataItem, this.valueField))) ? getter(dataItem, this.valueField) : dataItem;
|
|
818
|
-
if (newItem) {
|
|
819
|
-
if (!this.isAdaptive || !this.isActionSheetExpanded) {
|
|
820
|
-
this.value = [...this.value, newItem];
|
|
821
|
-
}
|
|
822
|
-
else {
|
|
823
|
-
this._valueHolder = [...this._valueHolder, newItem];
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
});
|
|
827
|
-
}
|
|
828
|
-
if (isPresent(event.removed) && event.removed.length > 0) {
|
|
829
|
-
event.removed.forEach((itemIndex) => {
|
|
830
|
-
const dataItem = this.dataService.itemAt(itemIndex);
|
|
831
|
-
const filter = (item) => getter(item, this.valueField) !== getter(dataItem, this.valueField);
|
|
832
|
-
if (!this.isAdaptive || !this.isActionSheetExpanded) {
|
|
833
|
-
this.value = this.value.filter(filter);
|
|
834
|
-
}
|
|
835
|
-
else {
|
|
836
|
-
this._valueHolder = this._valueHolder.filter(filter);
|
|
837
|
-
}
|
|
838
|
-
});
|
|
839
|
-
this.cdr.detectChanges();
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
else {
|
|
843
|
-
const isCustomItem = (isPresent(event.added) || isPresent(event.removed)) && (event.added === -1 || event.removed === -1);
|
|
844
|
-
if (isCustomItem) {
|
|
845
|
-
this.addCustomValue(this.text);
|
|
846
|
-
return; // The change is emited asynchronosly.
|
|
847
|
-
}
|
|
848
|
-
// Existing items.
|
|
849
|
-
if (isPresent(event.added)) {
|
|
850
|
-
const dataItem = this.dataService.itemAt(event.added);
|
|
851
|
-
const newItem = (this.valuePrimitive && isPresent(dataItem) && isPresent(getter(dataItem, this.valueField))) ? getter(dataItem, this.valueField) : dataItem;
|
|
852
|
-
if (!this.isAdaptive || !this.isActionSheetExpanded) {
|
|
853
|
-
this.value = [...this.value, newItem];
|
|
854
|
-
}
|
|
855
|
-
else {
|
|
856
|
-
this._valueHolder = [...this._valueHolder, newItem];
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
if (isPresent(event.removed)) {
|
|
860
|
-
const dataItem = this.dataService.itemAt(event.removed);
|
|
861
|
-
const filter = (item) => getter(item, this.valueField) !== getter(dataItem, this.valueField);
|
|
862
|
-
if (!this.isAdaptive || !this.isActionSheetExpanded) {
|
|
863
|
-
this.value = this.value.filter(filter);
|
|
864
|
-
}
|
|
865
|
-
else {
|
|
866
|
-
this._valueHolder = this._valueHolder.filter(filter);
|
|
867
|
-
}
|
|
868
|
-
this.selectionService.focused = event.removed;
|
|
869
|
-
this.cdr.detectChanges();
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
if (!this.isAdaptive || !this.isActionSheetExpanded) {
|
|
873
|
-
this.emitValueChange();
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
/**
|
|
877
|
-
* @hidden
|
|
878
|
-
*/
|
|
879
|
-
setState(value) {
|
|
880
|
-
let data = this.dataService.data;
|
|
881
|
-
if (this.dataService.grouped) {
|
|
882
|
-
data = data.filter(item => !item.header).map(item => item.value);
|
|
883
|
-
}
|
|
884
|
-
const selection = selectedIndices(this.value, data, this.valueField);
|
|
885
|
-
this.selectionService.resetSelection(selection);
|
|
886
|
-
if (this.disabledItemsService.isIndexDisabled(this.selectionService.focused)) {
|
|
887
|
-
this.selectionService.focused = this.firstFocusableIndex(0);
|
|
888
|
-
}
|
|
889
|
-
if (this.isOpen && this.selectionService.focused === undefined) {
|
|
890
|
-
if (this.dataService.itemsCount > 0) {
|
|
891
|
-
this.selectionService.focused = this.firstFocusableIndex(0);
|
|
892
|
-
if (this.allowCustom) {
|
|
893
|
-
this.selectionService.focused = 0;
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
else if (this.allowCustom) {
|
|
897
|
-
this.selectionService.focused = -1;
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
if (this.valuePrimitive && !this.valueField) {
|
|
901
|
-
this.selectedDataItems = value.slice();
|
|
902
|
-
}
|
|
903
|
-
if (isObjectArray(value) || this.valuePrimitive && this.valueField) {
|
|
904
|
-
this.selectedDataItems = resolveAllValues(value, data, this.valueField);
|
|
905
|
-
}
|
|
906
|
-
if (this.selectedDataItems.length < value.length) {
|
|
907
|
-
this.selectedDataItems = value
|
|
908
|
-
.map(current => {
|
|
909
|
-
const dataItem = this.selectedDataItems.find(item => getter(item, this.valueField) === getter(current, this.valueField));
|
|
910
|
-
return isPresent(dataItem) ? dataItem : this.resolveDataItemFromTags(current);
|
|
911
|
-
})
|
|
912
|
-
.filter(dataItem => isPresent(dataItem));
|
|
913
|
-
}
|
|
914
|
-
this.tags = this.tagMapper(this.selectedDataItems.slice(0));
|
|
915
|
-
this.disabledIndices = this.disabledItemsMapper();
|
|
916
|
-
this.cdr.markForCheck();
|
|
917
|
-
}
|
|
918
|
-
/**
|
|
919
|
-
* @hidden
|
|
920
|
-
*/
|
|
921
|
-
handleFilter(text) {
|
|
922
|
-
if (this.isActionSheetExpanded && this.allowCustom && this.isCustomValueSelected) {
|
|
923
|
-
this.addCustomValue(this.text);
|
|
924
|
-
this.addCustomValue(text);
|
|
925
|
-
}
|
|
926
|
-
this.text = text;
|
|
927
|
-
if (text && !this.isOpen) {
|
|
928
|
-
this.openPopup();
|
|
929
|
-
}
|
|
930
|
-
if (this.filterable) {
|
|
931
|
-
this.filterChange.emit(text);
|
|
932
|
-
}
|
|
933
|
-
else {
|
|
934
|
-
this.searchTextAndFocus(text);
|
|
935
|
-
}
|
|
936
|
-
this.searchbar.setInputSize();
|
|
937
|
-
}
|
|
938
|
-
/**
|
|
939
|
-
* @hidden
|
|
940
|
-
*/
|
|
941
|
-
pageChange(event) {
|
|
942
|
-
const virtual = this.virtual;
|
|
943
|
-
virtual.skip = event.skip;
|
|
944
|
-
}
|
|
945
|
-
/**
|
|
946
|
-
* @hidden
|
|
947
|
-
*/
|
|
948
|
-
clearFilter() {
|
|
949
|
-
if (this.filterable && this.text) {
|
|
950
|
-
this.filterChange.emit("");
|
|
951
|
-
}
|
|
952
|
-
this.text = "";
|
|
953
|
-
/* Clearing the value from the input as the setInputSize calculation will be incorrect otherwise.
|
|
954
|
-
Calling cdr.detectChanges to clear the input value as a result of property binding
|
|
955
|
-
causes JAWS to read outdated tag values in IE upon tag selection for some reason. */
|
|
956
|
-
this.searchbar.input.nativeElement.value = "";
|
|
957
|
-
this.searchbar.setInputSize();
|
|
958
|
-
}
|
|
959
|
-
/**
|
|
960
|
-
* @hidden
|
|
961
|
-
*/
|
|
962
|
-
handleNavigate(event) {
|
|
963
|
-
const code = normalizeKeys(event);
|
|
964
|
-
const navigateInput = this.text && code !== Keys.ArrowDown && code !== Keys.ArrowUp;
|
|
965
|
-
const selectValue = this.text && code === Keys.Enter || code === Keys.Escape;
|
|
966
|
-
const deleteTag = !this.text && code === Keys.Backspace && this.tags.length > 0;
|
|
967
|
-
if (code === Keys.Backspace && this.isActionSheetExpanded) {
|
|
968
|
-
return;
|
|
969
|
-
}
|
|
970
|
-
if (deleteTag) {
|
|
971
|
-
this.handleBackspace();
|
|
972
|
-
return;
|
|
973
|
-
}
|
|
974
|
-
if (this.disabled || navigateInput && !selectValue) {
|
|
975
|
-
return;
|
|
976
|
-
}
|
|
977
|
-
const eventData = event;
|
|
978
|
-
const focused = isNaN(this.selectionService.focused) ? -1 : this.selectionService.focused;
|
|
979
|
-
const action = this.navigationService.process({
|
|
980
|
-
current: focused,
|
|
981
|
-
max: this.dataService.itemsCount - 1,
|
|
982
|
-
min: this.allowCustom && this.text ? -1 : 0,
|
|
983
|
-
open: this.isOpen,
|
|
984
|
-
originalEvent: eventData
|
|
985
|
-
});
|
|
986
|
-
if (action !== NavigationAction.Undefined &&
|
|
987
|
-
((action === NavigationAction.Enter && this.isOpen) || action !== NavigationAction.Enter) &&
|
|
988
|
-
(!this.isActionSheetExpanded && action === NavigationAction.Tab)) {
|
|
989
|
-
event.preventDefault();
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
/**
|
|
993
|
-
* @hidden
|
|
994
|
-
*/
|
|
995
|
-
handleRemoveTag({ tag }) {
|
|
996
|
-
const eventArgs = new RemoveTagEvent(tag);
|
|
997
|
-
if (this.disabled || this.readonly) {
|
|
998
|
-
return;
|
|
999
|
-
}
|
|
1000
|
-
this.focus();
|
|
1001
|
-
this.removeTag.emit(eventArgs);
|
|
1002
|
-
if (eventArgs.isDefaultPrevented()) {
|
|
1003
|
-
return;
|
|
1004
|
-
}
|
|
1005
|
-
if (tag instanceof Array) {
|
|
1006
|
-
this.removeGroupTag(tag);
|
|
1007
|
-
}
|
|
1008
|
-
else {
|
|
1009
|
-
this.removeSingleTag(tag);
|
|
1010
|
-
}
|
|
1011
|
-
this.cdr.detectChanges();
|
|
1012
|
-
}
|
|
1013
|
-
/**
|
|
1014
|
-
* @hidden
|
|
1015
|
-
*/
|
|
1016
|
-
clearAll(event) {
|
|
1017
|
-
event?.stopImmediatePropagation();
|
|
1018
|
-
event?.preventDefault();
|
|
1019
|
-
this.focus();
|
|
1020
|
-
this.clearFilter();
|
|
1021
|
-
this.selectionService.lastClickedIndex = null;
|
|
1022
|
-
const selected = this.selectionService.selected;
|
|
1023
|
-
this.value = this.value.filter((_item, index) => this.disabledItemsService.isIndexDisabled(selected[index]));
|
|
1024
|
-
this.emitValueChange();
|
|
1025
|
-
}
|
|
1026
|
-
/**
|
|
1027
|
-
* @hidden
|
|
1028
|
-
*/
|
|
1029
|
-
addCustomValue(text) {
|
|
1030
|
-
this.customValueSubject.next(text);
|
|
1031
|
-
}
|
|
1032
|
-
ngAfterContentChecked() {
|
|
1033
|
-
this.verifySettings();
|
|
1034
|
-
}
|
|
1035
|
-
ngDoCheck() {
|
|
1036
|
-
const valueChanges = this.differ && this.differ.diff(this.value);
|
|
1037
|
-
if (valueChanges && !this.valueChangeDetected) {
|
|
1038
|
-
this.setState(this.value);
|
|
1039
|
-
}
|
|
1040
|
-
this.valueChangeDetected = false;
|
|
1041
|
-
}
|
|
1042
|
-
ngOnInit() {
|
|
1043
|
-
this.renderer.removeAttribute(this.wrapper.nativeElement, "tabindex");
|
|
1044
|
-
this.createCustomValueStream();
|
|
1045
|
-
this.subs.add(this.localization
|
|
1046
|
-
.changes.subscribe(({ rtl }) => {
|
|
1047
|
-
this.direction = rtl ? 'rtl' : 'ltr';
|
|
1048
|
-
this.cdr.markForCheck();
|
|
1049
|
-
}));
|
|
1050
|
-
this.setState(this.value);
|
|
1051
|
-
this.setComponentClasses();
|
|
1052
|
-
this.initialized = true;
|
|
1053
|
-
}
|
|
1054
|
-
ngOnChanges(changes) {
|
|
1055
|
-
const virtual = this.virtual;
|
|
1056
|
-
const requestInitialData = virtual && changes.data && changes.data.isFirstChange();
|
|
1057
|
-
if (requestInitialData) {
|
|
1058
|
-
this.pageChange({ skip: 0, take: virtual.pageSize });
|
|
1059
|
-
}
|
|
1060
|
-
if (isChanged('valueNormalizer', changes)) {
|
|
1061
|
-
this.createCustomValueStream();
|
|
1062
|
-
}
|
|
1063
|
-
if (anyChanged(['textField', 'valueField', 'valuePrimitive'], changes)) {
|
|
1064
|
-
this.setState(this.value);
|
|
1065
|
-
}
|
|
1066
|
-
}
|
|
1067
|
-
ngAfterViewInit() {
|
|
1068
|
-
this.windowSize = this.adaptiveService.size;
|
|
1069
|
-
this.cdr.detectChanges();
|
|
1070
|
-
this.searchbar.setInputSize();
|
|
1071
|
-
this.subs.add(this.renderer.listen(this.wrapper.nativeElement, 'mousedown', this.handleMousedown.bind(this)));
|
|
1072
|
-
this.subs.add(this.renderer.listen(this.wrapper.nativeElement, 'keydown', this.handleKeydown.bind(this)));
|
|
1073
|
-
this._zone.onStable.pipe(take(1)).subscribe(() => {
|
|
1074
|
-
const ariaLabel = this.searchbar.input.nativeElement.getAttribute('aria-labelledby') ||
|
|
1075
|
-
this.searchbar.input.nativeElement.getAttribute('data-kendo-label-id');
|
|
1076
|
-
if (ariaLabel) {
|
|
1077
|
-
this.renderer.setAttribute(this.tagList.hostElement.nativeElement, 'aria-labelledby', ariaLabel);
|
|
1078
|
-
}
|
|
1079
|
-
});
|
|
1080
|
-
}
|
|
1081
|
-
ngOnDestroy() {
|
|
1082
|
-
this._toggle(false);
|
|
1083
|
-
this.unsubscribeEvents();
|
|
1084
|
-
}
|
|
1085
|
-
/**
|
|
1086
|
-
* Toggles the visibility of the popup or actionSheet
|
|
1087
|
-
* ([see example]({% slug openstate_multiselect %}#toc-setting-the-initially-opened-component)).
|
|
1088
|
-
* If you use the `toggle` method to open or close the popup or actionSheet, the respective `open` and `close` events will not be fired.
|
|
1089
|
-
*
|
|
1090
|
-
* @param open - The state of the popup.
|
|
1091
|
-
*/
|
|
1092
|
-
toggle(open) {
|
|
1093
|
-
// The Promise is required for opening the popup on load.
|
|
1094
|
-
// Otherwise, the "Expression has changed..." type error will be thrown.
|
|
1095
|
-
Promise.resolve(null).then(() => {
|
|
1096
|
-
const shouldOpen = isPresent(open) ? open : !this._open;
|
|
1097
|
-
this._toggle(shouldOpen);
|
|
1098
|
-
this.cdr.markForCheck();
|
|
1099
|
-
});
|
|
1100
|
-
}
|
|
1101
|
-
/**
|
|
1102
|
-
* Returns the current open state. Returns `true` if the popup or actionSheet is open.
|
|
1103
|
-
*/
|
|
1104
|
-
get isOpen() {
|
|
1105
|
-
return isTruthy(this._open || this.isActionSheetExpanded);
|
|
1106
|
-
}
|
|
1107
|
-
/**
|
|
1108
|
-
* Resets the MultiSelect by clearing the text and value.
|
|
1109
|
-
* This method does not trigger the `selectionChange` and `valueChange` events.
|
|
1110
|
-
*/
|
|
1111
|
-
reset() {
|
|
1112
|
-
this.text = "";
|
|
1113
|
-
this.value = [];
|
|
1114
|
-
}
|
|
1115
|
-
/**
|
|
1116
|
-
* @hidden
|
|
1117
|
-
*/
|
|
1118
|
-
messageFor(key) {
|
|
1119
|
-
return this.localization.get(key);
|
|
1120
|
-
}
|
|
1121
|
-
// NG MODEL BINDINGS
|
|
1122
|
-
/**
|
|
1123
|
-
* @hidden
|
|
1124
|
-
*/
|
|
1125
|
-
writeValue(value) {
|
|
1126
|
-
this.value = value || [];
|
|
1127
|
-
}
|
|
1128
|
-
/**
|
|
1129
|
-
* @hidden
|
|
1130
|
-
*/
|
|
1131
|
-
registerOnChange(fn) {
|
|
1132
|
-
this.onChangeCallback = fn;
|
|
1133
|
-
}
|
|
1134
|
-
/**
|
|
1135
|
-
* @hidden
|
|
1136
|
-
*/
|
|
1137
|
-
registerOnTouched(fn) {
|
|
1138
|
-
this.onTouchedCallback = fn;
|
|
1139
|
-
}
|
|
1140
|
-
/**
|
|
1141
|
-
* @hidden
|
|
1142
|
-
*/
|
|
1143
|
-
setDisabledState(isDisabled) {
|
|
1144
|
-
this.cdr.markForCheck();
|
|
1145
|
-
this.disabled = isDisabled;
|
|
1146
|
-
}
|
|
1147
|
-
/**
|
|
1148
|
-
* @hidden
|
|
1149
|
-
*/
|
|
1150
|
-
onTagMapperChange() {
|
|
1151
|
-
this.tags = this.tagMapper(this.selectedDataItems.slice(0));
|
|
1152
|
-
this.cdr.markForCheck();
|
|
1153
|
-
}
|
|
1154
|
-
/**
|
|
1155
|
-
* @hidden
|
|
1156
|
-
*/
|
|
1157
|
-
handleClick() {
|
|
1158
|
-
this.windowSize = this.adaptiveService.size;
|
|
1159
|
-
if (this.isAdaptive) {
|
|
1160
|
-
this.togglePopup(true);
|
|
1161
|
-
}
|
|
1162
|
-
}
|
|
1163
|
-
onChangeCallback = (_) => { };
|
|
1164
|
-
onTouchedCallback = (_) => { };
|
|
1165
|
-
_placeholder = '';
|
|
1166
|
-
_open = false;
|
|
1167
|
-
_value = [];
|
|
1168
|
-
_popupSettings = { animate: true };
|
|
1169
|
-
_virtualSettings;
|
|
1170
|
-
_valuePrimitive;
|
|
1171
|
-
_checkboxes = { enabled: false };
|
|
1172
|
-
_isFocused = false;
|
|
1173
|
-
set isFocused(isFocused) {
|
|
1174
|
-
this.renderer[isFocused ? 'addClass' : 'removeClass'](this.wrapper.nativeElement, 'k-focus');
|
|
1175
|
-
this._isFocused = isFocused;
|
|
1176
|
-
}
|
|
1177
|
-
get isFocused() {
|
|
1178
|
-
return this._isFocused;
|
|
1179
|
-
}
|
|
1180
|
-
selectedDataItems = [];
|
|
1181
|
-
popupPointerDownHandler;
|
|
1182
|
-
isOpenPrevented = false;
|
|
1183
|
-
customValueSubject = new Subject();
|
|
1184
|
-
customValueSubscription;
|
|
1185
|
-
subs = new Subscription();
|
|
1186
|
-
touchstartDisposeHandler;
|
|
1187
|
-
direction;
|
|
1188
|
-
differ;
|
|
1189
|
-
valueChangeDetected;
|
|
1190
|
-
subscribeEvents() {
|
|
1191
|
-
if (!isDocumentAvailable()) {
|
|
1192
|
-
return;
|
|
1193
|
-
}
|
|
1194
|
-
const isOpen = () => this.isOpen;
|
|
1195
|
-
const isClosed = () => !this.isOpen;
|
|
1196
|
-
const isTagFocused = () => !this.isOpen && this.focusedTagIndex !== undefined;
|
|
1197
|
-
[
|
|
1198
|
-
this.selectionService.onChange.subscribe(this.handleItemChange.bind(this)),
|
|
1199
|
-
this.navigationService.esc.subscribe(() => {
|
|
1200
|
-
if (this.isOpen) {
|
|
1201
|
-
this.closePopup();
|
|
1202
|
-
}
|
|
1203
|
-
else if (this.isFocused && this.selectedDataItems.length > 0) {
|
|
1204
|
-
this.clearAll();
|
|
1205
|
-
}
|
|
1206
|
-
}),
|
|
1207
|
-
this.navigationService.enter.pipe(filter(isOpen)).subscribe(this.handleEnter.bind(this)),
|
|
1208
|
-
this.navigationService.open.subscribe(this.openPopup.bind(this)),
|
|
1209
|
-
this.navigationService.close.subscribe(this.handleClose.bind(this)),
|
|
1210
|
-
this.navigationService.up.pipe(filter(isOpen)).subscribe((event) => this.handleUp(event.index)),
|
|
1211
|
-
this.navigationService.home.pipe(filter(() => isClosed)).subscribe(this.handleHome.bind(this)),
|
|
1212
|
-
this.navigationService.end.pipe(filter(() => isClosed)).subscribe(this.handleEnd.bind(this)),
|
|
1213
|
-
this.navigationService.backspace.pipe(filter(isTagFocused)).subscribe(this.handleBackspace.bind(this)),
|
|
1214
|
-
this.navigationService.delete.pipe(filter(isTagFocused)).subscribe(this.handleDelete.bind(this)),
|
|
1215
|
-
this.navigationService.left.subscribe(this.direction === 'rtl' ? this.handleRightKey.bind(this) : this.handleLeftKey.bind(this)),
|
|
1216
|
-
this.navigationService.right.subscribe(this.direction === 'rtl' ? this.handleLeftKey.bind(this) : this.handleRightKey.bind(this)),
|
|
1217
|
-
this.navigationService.down.subscribe((event) => this.handleDownKey(event.index)),
|
|
1218
|
-
this.navigationService.selectprevious.pipe(filter(isOpen)).subscribe((event) => this.handleSelectUpDown(event)),
|
|
1219
|
-
this.navigationService.selectnext.pipe(filter(isOpen)).subscribe((event) => this.handleSelectUpDown(event)),
|
|
1220
|
-
this.navigationService.selectalltobeginning.pipe(filter(isOpen)).subscribe(() => this.handleSelectAllToBeginning()),
|
|
1221
|
-
this.navigationService.selectalltoend.pipe(filter(isOpen)).subscribe(() => this.handleSelectAllToEnd()),
|
|
1222
|
-
merge(this.navigationService.pagedown, this.navigationService.pageup).subscribe((event) => {
|
|
1223
|
-
if (this.isOpen) {
|
|
1224
|
-
event.originalEvent.preventDefault();
|
|
1225
|
-
const code = normalizeKeys(event.originalEvent);
|
|
1226
|
-
this.optionsList.scrollWithOnePage(NavigationAction[code]);
|
|
1227
|
-
}
|
|
1228
|
-
})
|
|
1229
|
-
].forEach(s => this.subs.add(s));
|
|
1230
|
-
}
|
|
1231
|
-
subscribeTouchEvents() {
|
|
1232
|
-
if (!isDocumentAvailable() || !touchEnabled) {
|
|
1233
|
-
return;
|
|
1234
|
-
}
|
|
1235
|
-
this._zone.runOutsideAngular(() =>
|
|
1236
|
-
// Roll up MultiSelect on iOS when tapped outside
|
|
1237
|
-
this.touchstartDisposeHandler = this.renderer.listen(document, 'touchstart', (e) => {
|
|
1238
|
-
const target = e.target;
|
|
1239
|
-
if ((this.isFocused || this.isOpen) && !inDropDown(this.wrapper, target, this.popupRef)) {
|
|
1240
|
-
this._zone.run(() => {
|
|
1241
|
-
this.blur();
|
|
1242
|
-
if (this.isOpen) {
|
|
1243
|
-
this.togglePopup(false);
|
|
1244
|
-
}
|
|
1245
|
-
});
|
|
1246
|
-
}
|
|
1247
|
-
}));
|
|
1248
|
-
}
|
|
1249
|
-
unsubscribeEvents() {
|
|
1250
|
-
if (!isDocumentAvailable()) {
|
|
1251
|
-
return;
|
|
1252
|
-
}
|
|
1253
|
-
this.subs.unsubscribe();
|
|
1254
|
-
if (this.customValueSubscription) {
|
|
1255
|
-
this.customValueSubscription.unsubscribe();
|
|
1256
|
-
}
|
|
1257
|
-
if (this.touchstartDisposeHandler) {
|
|
1258
|
-
this.touchstartDisposeHandler();
|
|
1259
|
-
}
|
|
1260
|
-
}
|
|
1261
|
-
removeGroupTag(dataItems) {
|
|
1262
|
-
let data = this.dataService.data;
|
|
1263
|
-
if (this.dataService.grouped) {
|
|
1264
|
-
data = data.filter(item => !item.header).map(item => item.value);
|
|
1265
|
-
}
|
|
1266
|
-
const dataItemValues = new Set(dataItems.map(item => getter(item, this.valueField)));
|
|
1267
|
-
this.value = this.value.filter(value => {
|
|
1268
|
-
const index = selectedIndices([value], data, this.valueField)[0];
|
|
1269
|
-
const isDataItemDisabled = this.disabledItemsService.isIndexDisabled(index);
|
|
1270
|
-
return !dataItemValues.has(getter(value, this.valueField)) || isDataItemDisabled;
|
|
1271
|
-
});
|
|
1272
|
-
this.emitValueChange();
|
|
1273
|
-
}
|
|
1274
|
-
removeSingleTag(dataItem) {
|
|
1275
|
-
let data = this.dataService.data;
|
|
1276
|
-
if (this.dataService.grouped) {
|
|
1277
|
-
data = data.filter(item => !item.header).map(item => item.value);
|
|
1278
|
-
}
|
|
1279
|
-
const index = selectedIndices([dataItem], data, this.valueField)[0];
|
|
1280
|
-
if (this.disabledItemsService.isIndexDisabled(index)) {
|
|
1281
|
-
return;
|
|
1282
|
-
}
|
|
1283
|
-
if (isNumber(index)) {
|
|
1284
|
-
this.selectionService.deselect(index);
|
|
1285
|
-
this.selectionService.focused = index;
|
|
1286
|
-
this.togglePopup(false);
|
|
1287
|
-
}
|
|
1288
|
-
else { // the deleted item is not present in the source
|
|
1289
|
-
const filter = item => getter(item, this.valueField) !== getter(dataItem, this.valueField);
|
|
1290
|
-
this.value = this.value.filter(filter);
|
|
1291
|
-
this.emitValueChange();
|
|
1292
|
-
}
|
|
1293
|
-
}
|
|
1294
|
-
/**
|
|
1295
|
-
* @hidden
|
|
1296
|
-
*
|
|
1297
|
-
* Determines which of the provided tags should be disabled and stores their position indices
|
|
1298
|
-
*/
|
|
1299
|
-
disabledItemsMapper() {
|
|
1300
|
-
const { selected } = this.selectionService;
|
|
1301
|
-
return new Set(this.selectedDataItems.reduce((indices, _item, index) => {
|
|
1302
|
-
if (this.disabledItemsService.isIndexDisabled(selected[index])) {
|
|
1303
|
-
indices.push(index);
|
|
1304
|
-
}
|
|
1305
|
-
return indices;
|
|
1306
|
-
}, []));
|
|
1307
|
-
}
|
|
1308
|
-
createCustomValueStream() {
|
|
1309
|
-
if (this.customValueSubscription) {
|
|
1310
|
-
this.customValueSubscription.unsubscribe();
|
|
1311
|
-
}
|
|
1312
|
-
this.customValueSubscription = this.customValueSubject.pipe(tap(() => {
|
|
1313
|
-
this.loading = true;
|
|
1314
|
-
this.disabled = true;
|
|
1315
|
-
this.cdr.detectChanges();
|
|
1316
|
-
}), this.valueNormalizer, catchError(() => {
|
|
1317
|
-
this.loading = false;
|
|
1318
|
-
this.disabled = false;
|
|
1319
|
-
if (this.autoClose) {
|
|
1320
|
-
this.togglePopup(false);
|
|
1321
|
-
}
|
|
1322
|
-
if (this.autoClose || !this.filterable) {
|
|
1323
|
-
this.clearFilter();
|
|
1324
|
-
}
|
|
1325
|
-
this.nextTick(() => {
|
|
1326
|
-
this.searchbar.focus();
|
|
1327
|
-
});
|
|
1328
|
-
this.createCustomValueStream();
|
|
1329
|
-
return of(null);
|
|
1330
|
-
}))
|
|
1331
|
-
.subscribe((normalizedValue) => {
|
|
1332
|
-
this.loading = false;
|
|
1333
|
-
this.disabled = false;
|
|
1334
|
-
if (isPresent(normalizedValue)) { // if valueNormalizer returns `null` or `undefined` custom value is discarded
|
|
1335
|
-
const newValue = this.valuePrimitive ? getter(normalizedValue, this.valueField) : normalizedValue;
|
|
1336
|
-
const itemIndex = this.dataService.indexOf(newValue);
|
|
1337
|
-
const customItem = itemIndex === -1;
|
|
1338
|
-
if (this.value.indexOf(newValue) === -1) {
|
|
1339
|
-
!this.isActionSheetExpanded && (this.tags = this.tagMapper([...this.selectedDataItems, normalizedValue]));
|
|
1340
|
-
if (!customItem) {
|
|
1341
|
-
this.selectionService.add(itemIndex);
|
|
1342
|
-
}
|
|
1343
|
-
else if (this.isActionSheetExpanded) {
|
|
1344
|
-
const isValueInHolder = this._valueHolder.some(item => getter(item, this.valueField) === newValue);
|
|
1345
|
-
if (isValueInHolder) {
|
|
1346
|
-
this._valueHolder = this._valueHolder.filter(item => getter(item, this.valueField) !== newValue);
|
|
1347
|
-
this.isCustomValueSelected = false;
|
|
1348
|
-
}
|
|
1349
|
-
else {
|
|
1350
|
-
this._valueHolder = [...this._valueHolder, newValue];
|
|
1351
|
-
this.isCustomValueSelected = true;
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
|
-
else {
|
|
1355
|
-
this.value = [...this.value, newValue];
|
|
1356
|
-
}
|
|
1357
|
-
}
|
|
1358
|
-
else if (!customItem && this.selectionService.isSelected(itemIndex)) {
|
|
1359
|
-
this.selectionService.deselect(itemIndex);
|
|
1360
|
-
this.selectionService.focused = itemIndex;
|
|
1361
|
-
}
|
|
1362
|
-
else if (this.isActionSheetExpanded) {
|
|
1363
|
-
this._valueHolder = this._valueHolder.filter(item => getter(item, this.valueField) !== newValue);
|
|
1364
|
-
this.isCustomValueSelected = false;
|
|
1365
|
-
}
|
|
1366
|
-
else {
|
|
1367
|
-
this.value = this.value.filter(item => getter(item, this.valueField) !== newValue);
|
|
1368
|
-
}
|
|
1369
|
-
!this.isActionSheetExpanded && this.emitValueChange();
|
|
1370
|
-
}
|
|
1371
|
-
if (this.autoClose) {
|
|
1372
|
-
this.togglePopup(false);
|
|
1373
|
-
}
|
|
1374
|
-
if ((this.autoClose || !this.filterable) && !this.isActionSheetExpanded) {
|
|
1375
|
-
this.clearFilter();
|
|
1376
|
-
}
|
|
1377
|
-
if (!this.isActionSheetExpanded) {
|
|
1378
|
-
this.nextTick(() => {
|
|
1379
|
-
this.searchbar.focus();
|
|
1380
|
-
});
|
|
1381
|
-
}
|
|
1382
|
-
});
|
|
1383
|
-
}
|
|
1384
|
-
handleItemChange(event) {
|
|
1385
|
-
this.change(event);
|
|
1386
|
-
if (this.autoClose && !event.preventClosingPopup && !this.isActionSheetExpanded) {
|
|
1387
|
-
this.togglePopup(false);
|
|
1388
|
-
}
|
|
1389
|
-
if ((this.autoClose || !this.filterable) && !this.isActionSheetExpanded) {
|
|
1390
|
-
this.clearFilter();
|
|
1391
|
-
}
|
|
1392
|
-
}
|
|
1393
|
-
handleMousedown(event) {
|
|
1394
|
-
if (event.target.closest('.k-input-prefix') || event.target.closest('.k-input-suffix')) {
|
|
1395
|
-
return;
|
|
1396
|
-
}
|
|
1397
|
-
if (!this.isActionSheetExpanded) {
|
|
1398
|
-
const inputElement = this.searchbar.input.nativeElement;
|
|
1399
|
-
if (event.button === 0) {
|
|
1400
|
-
if (this.isFocused && (this.isOpen || this.isOpenPrevented) && event.target === inputElement) {
|
|
1401
|
-
return;
|
|
1402
|
-
}
|
|
1403
|
-
if (!touchEnabled || (touchEnabled && event.target.tagName !== 'SPAN')) {
|
|
1404
|
-
this.searchbar.focus();
|
|
1405
|
-
}
|
|
1406
|
-
// The check is needed otherwise when appended to the component, the popup reopens on click
|
|
1407
|
-
// https://github.com/telerik/kendo-angular/issues/3738
|
|
1408
|
-
if ((this.popupRef && this.popupRef.popupElement.contains(event.target))) {
|
|
1409
|
-
return;
|
|
1410
|
-
}
|
|
1411
|
-
event.preventDefault();
|
|
1412
|
-
this.togglePopup(!this.isOpen);
|
|
1413
|
-
}
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
handleKeydown(event) {
|
|
1417
|
-
const code = normalizeKeys(event);
|
|
1418
|
-
if (this.isFocused && this.isOpen && (event.ctrlKey || event.metaKey) && code === Keys.KeyA) {
|
|
1419
|
-
event.preventDefault();
|
|
1420
|
-
this.handleSelectAll();
|
|
1421
|
-
}
|
|
1422
|
-
}
|
|
1423
|
-
handleEnter(event) {
|
|
1424
|
-
const service = this.selectionService;
|
|
1425
|
-
const focusedIndex = this.selectionService.focused;
|
|
1426
|
-
this.selectionService.lastClickedIndex = focusedIndex;
|
|
1427
|
-
if (this.isOpen) {
|
|
1428
|
-
event.originalEvent.preventDefault();
|
|
1429
|
-
}
|
|
1430
|
-
if (focusedIndex === -1) {
|
|
1431
|
-
if (this.allowCustom && this.text) {
|
|
1432
|
-
this.addCustomValue(this.text);
|
|
1433
|
-
}
|
|
1434
|
-
return; // Clear filter & close are done at customValueSubscription due to race conditions.
|
|
1435
|
-
}
|
|
1436
|
-
if (service.isSelected(focusedIndex)) {
|
|
1437
|
-
service.deselect(focusedIndex);
|
|
1438
|
-
service.focused = focusedIndex;
|
|
1439
|
-
}
|
|
1440
|
-
else {
|
|
1441
|
-
service.add(focusedIndex);
|
|
1442
|
-
}
|
|
1443
|
-
if (this.autoClose && !this.isActionSheetExpanded) {
|
|
1444
|
-
this.togglePopup(false);
|
|
1445
|
-
}
|
|
1446
|
-
if (this.autoClose || !this.filterable) {
|
|
1447
|
-
this.clearFilter();
|
|
1448
|
-
}
|
|
1449
|
-
}
|
|
1450
|
-
handleClose() {
|
|
1451
|
-
this.closePopup();
|
|
1452
|
-
this.searchbar.focus();
|
|
1453
|
-
}
|
|
1454
|
-
handleEnd() {
|
|
1455
|
-
this.focusedTagIndex = this.tags.length - 1;
|
|
1456
|
-
}
|
|
1457
|
-
handleHome() {
|
|
1458
|
-
this.focusedTagIndex = 0;
|
|
1459
|
-
}
|
|
1460
|
-
sortSelectionAscending() {
|
|
1461
|
-
return this.selectionService.selected.sort((a, b) => a - b);
|
|
1462
|
-
}
|
|
1463
|
-
handleSelectAll() {
|
|
1464
|
-
const selectedItemsCount = this.selectionService.selected.length;
|
|
1465
|
-
const dataItemsCount = this.dataService.data.length;
|
|
1466
|
-
const dataItemsWithoutHeadersCount = this.dataService.data.filter(i => !i.header).length;
|
|
1467
|
-
if ((!this.dataService.grouped && selectedItemsCount === dataItemsCount) ||
|
|
1468
|
-
(this.dataService.grouped && selectedItemsCount === dataItemsWithoutHeadersCount)) {
|
|
1469
|
-
this.clearAll();
|
|
1470
|
-
}
|
|
1471
|
-
else {
|
|
1472
|
-
this.selectionService.selectFromTo(0, dataItemsCount - 1);
|
|
1473
|
-
this.selectionService.emitMultipleAddedRemoved();
|
|
1474
|
-
}
|
|
1475
|
-
}
|
|
1476
|
-
handleSelectAllToBeginning() {
|
|
1477
|
-
const selectedItemsCount = this.selectionService.selected.length;
|
|
1478
|
-
const dataItemsCount = this.dataService.data.length;
|
|
1479
|
-
const focusedItem = this.selectionService.focused;
|
|
1480
|
-
const largestIndex = this.sortSelectionAscending()[selectedItemsCount - 1];
|
|
1481
|
-
if (selectedItemsCount !== dataItemsCount) {
|
|
1482
|
-
this.selectionService.unselectFromTo(largestIndex, focusedItem + 1);
|
|
1483
|
-
this.selectionService.selectFromTo(0, focusedItem);
|
|
1484
|
-
}
|
|
1485
|
-
this.nextTick(() => this.selectionService.focus(0));
|
|
1486
|
-
this.selectionService.emitMultipleAddedRemoved();
|
|
1487
|
-
}
|
|
1488
|
-
handleSelectAllToEnd() {
|
|
1489
|
-
const selectedItemsCount = this.selectionService.selected.length;
|
|
1490
|
-
const dataItemsCount = this.dataService.data.length;
|
|
1491
|
-
const focusedItem = this.selectionService.focused;
|
|
1492
|
-
if (selectedItemsCount !== dataItemsCount) {
|
|
1493
|
-
this.selectionService.unselectFromTo(focusedItem - 1, 0);
|
|
1494
|
-
this.selectionService.selectFromTo(focusedItem, dataItemsCount - 1);
|
|
1495
|
-
}
|
|
1496
|
-
if (this.dataService.grouped) {
|
|
1497
|
-
const lastItemIndex = this.dataService.groupIndices[this.dataService.groupIndices.length - 1] - 1;
|
|
1498
|
-
this.nextTick(() => this.selectionService.focus(lastItemIndex));
|
|
1499
|
-
}
|
|
1500
|
-
else {
|
|
1501
|
-
this.nextTick(() => this.selectionService.focus(dataItemsCount - 1));
|
|
1502
|
-
}
|
|
1503
|
-
this.selectionService.emitMultipleAddedRemoved();
|
|
1504
|
-
}
|
|
1505
|
-
handleSelectUpDown(event) {
|
|
1506
|
-
const focusedIndex = this.selectionService.focused;
|
|
1507
|
-
if (!isPresent(focusedIndex)) {
|
|
1508
|
-
return;
|
|
1509
|
-
}
|
|
1510
|
-
let indexToSelect;
|
|
1511
|
-
if (event.originalEvent.key === 'ArrowUp') {
|
|
1512
|
-
indexToSelect = focusedIndex > 0 ? focusedIndex - 1 : focusedIndex;
|
|
1513
|
-
}
|
|
1514
|
-
else {
|
|
1515
|
-
indexToSelect = focusedIndex < this.dataService.data.length - 1 ? focusedIndex + 1 : focusedIndex;
|
|
1516
|
-
}
|
|
1517
|
-
if (!isPresent(this.selectionService.lastClickedIndex)) {
|
|
1518
|
-
this.selectionService.lastClickedIndex = focusedIndex;
|
|
1519
|
-
}
|
|
1520
|
-
this.selectRangeFromTo(indexToSelect);
|
|
1521
|
-
}
|
|
1522
|
-
/**
|
|
1523
|
-
* Selects all items between the focused item and the last clicked item (index). Also removes all other selected items.
|
|
1524
|
-
*/
|
|
1525
|
-
selectRangeFromTo(indexToSelect) {
|
|
1526
|
-
const lastClickedIndex = this.selectionService.lastClickedIndex;
|
|
1527
|
-
if (lastClickedIndex > indexToSelect) {
|
|
1528
|
-
this.selectionService.unselectNotNeededIndices(indexToSelect, lastClickedIndex, this.dataService.data.length);
|
|
1529
|
-
this.selectionService.selectFromTo(indexToSelect, this.selectionService.lastClickedIndex);
|
|
1530
|
-
this.selectionService.emitMultipleAddedRemoved();
|
|
1531
|
-
}
|
|
1532
|
-
else {
|
|
1533
|
-
this.selectionService.unselectNotNeededIndices(lastClickedIndex, indexToSelect, this.dataService.data.length);
|
|
1534
|
-
this.selectionService.selectFromTo(lastClickedIndex, indexToSelect);
|
|
1535
|
-
this.selectionService.emitMultipleAddedRemoved();
|
|
1536
|
-
}
|
|
1537
|
-
this.nextTick(() => this.selectionService.focus(indexToSelect));
|
|
1538
|
-
}
|
|
1539
|
-
handleUp(index) {
|
|
1540
|
-
this.selectionService.focused = index;
|
|
1541
|
-
}
|
|
1542
|
-
handleBackspace() {
|
|
1543
|
-
if (this.focusedTagIndex !== undefined) {
|
|
1544
|
-
this.handleDelete();
|
|
1545
|
-
}
|
|
1546
|
-
else {
|
|
1547
|
-
this.handleRemoveTag({ tag: this.tags[this.tags.length - 1] });
|
|
1548
|
-
this.searchbar.focus();
|
|
1549
|
-
}
|
|
1550
|
-
}
|
|
1551
|
-
handleDelete() {
|
|
1552
|
-
this.handleRemoveTag({ tag: this.tags[this.focusedTagIndex] });
|
|
1553
|
-
if (this.focusedTagIndex === this.tags.length) {
|
|
1554
|
-
this.focusedTagIndex = undefined;
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1557
|
-
handleLeftKey() {
|
|
1558
|
-
if (this.focusedTagIndex === undefined || this.focusedTagIndex < 0) {
|
|
1559
|
-
this.focusedTagIndex = this.tags.length - 1;
|
|
1560
|
-
}
|
|
1561
|
-
else if (this.focusedTagIndex !== 0) {
|
|
1562
|
-
this.focusedTagIndex--;
|
|
1563
|
-
}
|
|
1564
|
-
}
|
|
1565
|
-
handleDownKey(index) {
|
|
1566
|
-
if (this.isOpen) {
|
|
1567
|
-
this.selectionService.focused = index || this.firstFocusableIndex(0);
|
|
1568
|
-
}
|
|
1569
|
-
else {
|
|
1570
|
-
this.openPopup();
|
|
1571
|
-
}
|
|
1572
|
-
}
|
|
1573
|
-
handleRightKey() {
|
|
1574
|
-
const last = this.tags.length - 1;
|
|
1575
|
-
if (this.focusedTagIndex === last) {
|
|
1576
|
-
this.focusedTagIndex = undefined;
|
|
1577
|
-
}
|
|
1578
|
-
else if (this.focusedTagIndex < last) {
|
|
1579
|
-
this.focusedTagIndex++;
|
|
1580
|
-
}
|
|
1581
|
-
}
|
|
1582
|
-
findIndex(text, startsFrom = 0) {
|
|
1583
|
-
let itemText;
|
|
1584
|
-
text = text.toLowerCase();
|
|
1585
|
-
const index = this.dataService.findIndex(item => {
|
|
1586
|
-
if (this.dataService.grouped) {
|
|
1587
|
-
itemText = getter(item.value, this.textField);
|
|
1588
|
-
}
|
|
1589
|
-
else {
|
|
1590
|
-
itemText = getter(item, this.textField);
|
|
1591
|
-
}
|
|
1592
|
-
itemText = !isPresent(itemText) ? "" : itemText.toString().toLowerCase();
|
|
1593
|
-
return text && itemText.startsWith(text);
|
|
1594
|
-
}, startsFrom);
|
|
1595
|
-
if (this.disabledItemsService.isIndexDisabled(index)) {
|
|
1596
|
-
return (index + 1 > this.dataService.itemsCount) ? -1 : this.findIndex(text, index + 1);
|
|
1597
|
-
}
|
|
1598
|
-
else {
|
|
1599
|
-
return index;
|
|
1600
|
-
}
|
|
1601
|
-
}
|
|
1602
|
-
searchTextAndFocus(text) {
|
|
1603
|
-
const index = this.findIndex(text);
|
|
1604
|
-
this.selectionService.focused = index;
|
|
1605
|
-
}
|
|
1606
|
-
closePopup() {
|
|
1607
|
-
this.togglePopup(false);
|
|
1608
|
-
this.focusedTagIndex = undefined;
|
|
1609
|
-
}
|
|
1610
|
-
openPopup() {
|
|
1611
|
-
this.togglePopup(true);
|
|
1612
|
-
this.focusedTagIndex = undefined;
|
|
1613
|
-
}
|
|
1614
|
-
/**
|
|
1615
|
-
* @hidden
|
|
1616
|
-
*/
|
|
1617
|
-
togglePopup(open) {
|
|
1618
|
-
const isDisabled = this.disabled || this.readonly;
|
|
1619
|
-
const sameState = this.isOpen === open;
|
|
1620
|
-
if (isDisabled || sameState) {
|
|
1621
|
-
return;
|
|
1622
|
-
}
|
|
1623
|
-
const isDefaultPrevented = this.triggerPopupEvents(open);
|
|
1624
|
-
if (open) {
|
|
1625
|
-
this.isOpenPrevented = isDefaultPrevented;
|
|
1626
|
-
}
|
|
1627
|
-
if (!isDefaultPrevented) {
|
|
1628
|
-
this._toggle(open);
|
|
1629
|
-
}
|
|
1630
|
-
}
|
|
1631
|
-
triggerPopupEvents(open) {
|
|
1632
|
-
const eventArgs = new PreventableEvent();
|
|
1633
|
-
if (open) {
|
|
1634
|
-
this.open.emit(eventArgs);
|
|
1635
|
-
}
|
|
1636
|
-
else {
|
|
1637
|
-
this.close.emit(eventArgs);
|
|
1638
|
-
}
|
|
1639
|
-
return eventArgs.isDefaultPrevented();
|
|
1640
|
-
}
|
|
1641
|
-
_toggle(open) {
|
|
1642
|
-
this._open = open;
|
|
1643
|
-
this.destroyPopup();
|
|
1644
|
-
if (this.isActionSheetExpanded) {
|
|
1645
|
-
this.actionSheet.toggle(false);
|
|
1646
|
-
this.closed.emit();
|
|
1647
|
-
this.isFocused = false;
|
|
1648
|
-
}
|
|
1649
|
-
if (this._open) {
|
|
1650
|
-
this.createPopup();
|
|
1651
|
-
}
|
|
1652
|
-
}
|
|
1653
|
-
destroyPopup() {
|
|
1654
|
-
if (this.popupRef) {
|
|
1655
|
-
this.popupRef.popupElement
|
|
1656
|
-
.removeEventListener('pointerdown', this.popupPointerDownHandler);
|
|
1657
|
-
this.popupRef.close();
|
|
1658
|
-
this.popupRef = null;
|
|
1659
|
-
}
|
|
1660
|
-
}
|
|
1661
|
-
createPopup() {
|
|
1662
|
-
if (this.virtual) {
|
|
1663
|
-
this.virtual.skip = 0;
|
|
1664
|
-
}
|
|
1665
|
-
this.windowSize = this.adaptiveService.size;
|
|
1666
|
-
if (this.isAdaptive) {
|
|
1667
|
-
this.openActionSheet();
|
|
1668
|
-
return;
|
|
1669
|
-
}
|
|
1670
|
-
const horizontalAlign = this.direction === "rtl" ? "right" : "left";
|
|
1671
|
-
const anchorPosition = { horizontal: horizontalAlign, vertical: "bottom" };
|
|
1672
|
-
const popupPosition = { horizontal: horizontalAlign, vertical: "top" };
|
|
1673
|
-
const appendToComponent = typeof this.popupSettings.appendTo === 'string' && this.popupSettings.appendTo === 'component';
|
|
1674
|
-
this.popupRef = this.popupService.open({
|
|
1675
|
-
anchor: this.wrapper,
|
|
1676
|
-
anchorAlign: anchorPosition,
|
|
1677
|
-
animate: this.popupSettings.animate,
|
|
1678
|
-
appendTo: this.appendTo,
|
|
1679
|
-
content: this.popupTemplate,
|
|
1680
|
-
popupAlign: popupPosition,
|
|
1681
|
-
popupClass: this.listContainerClasses,
|
|
1682
|
-
positionMode: appendToComponent ? 'fixed' : 'absolute'
|
|
1683
|
-
});
|
|
1684
|
-
const popupWrapper = this.popupRef.popupElement;
|
|
1685
|
-
const { min, max } = this.width;
|
|
1686
|
-
if (!this.appendTo) {
|
|
1687
|
-
this.renderer.setAttribute(popupWrapper, 'role', 'region');
|
|
1688
|
-
this.renderer.setAttribute(popupWrapper, 'aria-label', this.messageFor('popupLabel'));
|
|
1689
|
-
}
|
|
1690
|
-
popupWrapper.addEventListener('pointerdown', this.popupPointerDownHandler);
|
|
1691
|
-
popupWrapper.style.minWidth = min;
|
|
1692
|
-
popupWrapper.style.width = max;
|
|
1693
|
-
popupWrapper.style.height = this.height;
|
|
1694
|
-
popupWrapper.setAttribute("dir", this.direction);
|
|
1695
|
-
this.popupRef.popupOpen.subscribe(() => {
|
|
1696
|
-
this.cdr.detectChanges();
|
|
1697
|
-
if (!this.dataService.grouped) {
|
|
1698
|
-
setListBoxAriaLabelledBy(this.optionsList, this.searchbar.input, this.renderer);
|
|
1699
|
-
}
|
|
1700
|
-
this.optionsList.scrollToItem(this.selectionService.focused);
|
|
1701
|
-
this.selectionService.focus(this.selectionService.focused);
|
|
1702
|
-
this.opened.emit();
|
|
1703
|
-
});
|
|
1704
|
-
this.popupRef.popupClose.subscribe(() => {
|
|
1705
|
-
this.closed.emit();
|
|
1706
|
-
});
|
|
1707
|
-
this.popupRef.popupAnchorViewportLeave.subscribe(() => {
|
|
1708
|
-
this.togglePopup(false);
|
|
1709
|
-
});
|
|
1710
|
-
}
|
|
1711
|
-
emitValueChange() {
|
|
1712
|
-
this.onChangeCallback(this.value);
|
|
1713
|
-
this.valueChange.emit(this.value);
|
|
1714
|
-
}
|
|
1715
|
-
resolveDataItemFromTags(value) {
|
|
1716
|
-
if (!(this.tags && this.tags.length && isPresent(value))) {
|
|
1717
|
-
return undefined;
|
|
1718
|
-
}
|
|
1719
|
-
// Flattening the tags array in case of a summary tag occurrence.
|
|
1720
|
-
const tags = this.tags.reduce((acc, tag) => {
|
|
1721
|
-
const items = isArray(tag) ? tag : [tag];
|
|
1722
|
-
acc.push(...items);
|
|
1723
|
-
return acc;
|
|
1724
|
-
}, []);
|
|
1725
|
-
return tags.find(tag => getter(tag, this.valueField) === getter(value, this.valueField));
|
|
1726
|
-
}
|
|
1727
|
-
firstFocusableIndex(index) {
|
|
1728
|
-
const maxIndex = this.dataService.itemsCount;
|
|
1729
|
-
if (this.disabledItemsService.isIndexDisabled(index)) {
|
|
1730
|
-
const nextIndex = index + 1;
|
|
1731
|
-
return (nextIndex < maxIndex) ? this.firstFocusableIndex(nextIndex) : undefined;
|
|
1732
|
-
}
|
|
1733
|
-
else {
|
|
1734
|
-
return index;
|
|
1735
|
-
}
|
|
1736
|
-
}
|
|
1737
|
-
nextTick(f) {
|
|
1738
|
-
this._zone.runOutsideAngular(() => {
|
|
1739
|
-
// Use `setTimeout` instead of a resolved promise
|
|
1740
|
-
// because the latter does not wait long enough.
|
|
1741
|
-
setTimeout(() => this._zone.run(f));
|
|
1742
|
-
});
|
|
1743
|
-
}
|
|
1744
|
-
setComponentClasses() {
|
|
1745
|
-
if (this.size !== 'none') {
|
|
1746
|
-
this.renderer.addClass(this.wrapper.nativeElement, getSizeClass('input', this.size));
|
|
1747
|
-
}
|
|
1748
|
-
if (this.rounded !== 'none') {
|
|
1749
|
-
this.renderer.addClass(this.wrapper.nativeElement, getRoundedClass(this.rounded));
|
|
1750
|
-
}
|
|
1751
|
-
if (this.fillMode !== 'none') {
|
|
1752
|
-
this.renderer.addClass(this.wrapper.nativeElement, getFillModeClass('input', this.fillMode));
|
|
1753
|
-
}
|
|
1754
|
-
}
|
|
1755
|
-
openActionSheet() {
|
|
1756
|
-
this.actionSheet.toggle(true);
|
|
1757
|
-
// Stores the current value state until the user either accepts or cancels it
|
|
1758
|
-
this._valueHolder = [...this.value];
|
|
1759
|
-
this.cdr.detectChanges();
|
|
1760
|
-
if (!this.dataService.grouped) {
|
|
1761
|
-
setListBoxAriaLabelledBy(this.optionsList, this.searchbar.input, this.renderer);
|
|
1762
|
-
}
|
|
1763
|
-
this.adaptiveTitle = setActionSheetTitle(this.searchbar.input, this.adaptiveTitle);
|
|
1764
|
-
this.cdr.detectChanges();
|
|
1765
|
-
this.opened.emit();
|
|
1766
|
-
this.optionsList.scrollToItem(this.selectionService.focused);
|
|
1767
|
-
this.selectionService.focus(this.selectionService.focused);
|
|
1768
|
-
this.actionSheetSearchBar.focus();
|
|
1769
|
-
}
|
|
1770
|
-
blurComponent() {
|
|
1771
|
-
if (!this.isFocused) {
|
|
1772
|
-
return;
|
|
1773
|
-
}
|
|
1774
|
-
this.isFocused = false;
|
|
1775
|
-
if (hasObservers(this.onBlur) ||
|
|
1776
|
-
hasObservers(this.filterChange) ||
|
|
1777
|
-
hasObservers(this.close) ||
|
|
1778
|
-
isUntouched(this.wrapper.nativeElement)) {
|
|
1779
|
-
this._zone.run(() => {
|
|
1780
|
-
this.closePopup();
|
|
1781
|
-
if (!(this.isOpen && this.allowCustom)) {
|
|
1782
|
-
this.clearFilter();
|
|
1783
|
-
}
|
|
1784
|
-
this.onBlur.emit();
|
|
1785
|
-
this.onTouchedCallback();
|
|
1786
|
-
});
|
|
1787
|
-
}
|
|
1788
|
-
else {
|
|
1789
|
-
if (!this.allowCustom) {
|
|
1790
|
-
this.clearFilter();
|
|
1791
|
-
}
|
|
1792
|
-
this.closePopup();
|
|
1793
|
-
}
|
|
1794
|
-
}
|
|
1795
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MultiSelectComponent, deps: [{ token: i0.ElementRef }, { token: i1.LocalizationService }, { token: i2.PopupService }, { token: i3.DataService }, { token: i4.SelectionService }, { token: i5.NavigationService }, { token: i6.DisabledItemsService }, { token: i0.ChangeDetectorRef }, { token: i0.KeyValueDiffers }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: i0.Injector }, { token: i0.ElementRef }, { token: i7.AdaptiveService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1796
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: MultiSelectComponent, isStandalone: true, selector: "kendo-multiselect", inputs: { showStickyHeader: "showStickyHeader", focusableId: "focusableId", autoClose: "autoClose", loading: "loading", data: "data", value: "value", valueField: "valueField", textField: "textField", tabindex: "tabindex", tabIndex: "tabIndex", size: "size", rounded: "rounded", fillMode: "fillMode", placeholder: "placeholder", adaptiveMode: "adaptiveMode", adaptiveTitle: "adaptiveTitle", adaptiveSubtitle: "adaptiveSubtitle", disabled: "disabled", itemDisabled: "itemDisabled", checkboxes: "checkboxes", readonly: "readonly", filterable: "filterable", virtual: "virtual", popupSettings: "popupSettings", listHeight: "listHeight", valuePrimitive: "valuePrimitive", clearButton: "clearButton", tagMapper: "tagMapper", allowCustom: "allowCustom", valueNormalizer: "valueNormalizer", inputAttributes: "inputAttributes" }, outputs: { filterChange: "filterChange", valueChange: "valueChange", open: "open", opened: "opened", close: "close", closed: "closed", onFocus: "focus", onBlur: "blur", inputFocus: "inputFocus", inputBlur: "inputBlur", removeTag: "removeTag" }, host: { properties: { "class.k-readonly": "this.readonly", "class.k-multiselect": "this.hostClasses", "class.k-input": "this.hostClasses", "attr.dir": "this.dir", "class.k-disabled": "this.disabledClass", "class.k-loading": "this.isLoading" } }, providers: [
|
|
1797
|
-
MULTISELECT_VALUE_ACCESSOR,
|
|
1798
|
-
DataService,
|
|
1799
|
-
SelectionService,
|
|
1800
|
-
NavigationService,
|
|
1801
|
-
DisabledItemsService,
|
|
1802
|
-
LocalizationService,
|
|
1803
|
-
{
|
|
1804
|
-
provide: L10N_PREFIX,
|
|
1805
|
-
useValue: 'kendo.multiselect'
|
|
1806
|
-
},
|
|
1807
|
-
{
|
|
1808
|
-
provide: FilterableComponent, useExisting: forwardRef(() => MultiSelectComponent)
|
|
1809
|
-
},
|
|
1810
|
-
{
|
|
1811
|
-
provide: KendoInput, useExisting: forwardRef(() => MultiSelectComponent)
|
|
1812
|
-
}
|
|
1813
|
-
], queries: [{ propertyName: "template", first: true, predicate: ItemTemplateDirective, descendants: true }, { propertyName: "customItemTemplate", first: true, predicate: CustomItemTemplateDirective, descendants: true }, { propertyName: "groupTemplate", first: true, predicate: GroupTemplateDirective, descendants: true }, { propertyName: "fixedGroupTemplate", first: true, predicate: FixedGroupTemplateDirective, descendants: true }, { propertyName: "headerTemplate", first: true, predicate: HeaderTemplateDirective, descendants: true }, { propertyName: "footerTemplate", first: true, predicate: FooterTemplateDirective, descendants: true }, { propertyName: "tagTemplate", first: true, predicate: TagTemplateDirective, descendants: true }, { propertyName: "groupTagTemplate", first: true, predicate: GroupTagTemplateDirective, descendants: true }, { propertyName: "noDataTemplate", first: true, predicate: NoDataTemplateDirective, descendants: true }, { propertyName: "suffixTemplate", first: true, predicate: SuffixTemplateDirective, descendants: true }, { propertyName: "prefixTemplate", first: true, predicate: PrefixTemplateDirective, descendants: true }], viewQueries: [{ propertyName: "adaptiveRendererComponent", first: true, predicate: AdaptiveRendererComponent, descendants: true }, { propertyName: "container", first: true, predicate: ["container"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "searchbar", first: true, predicate: SearchBarComponent, descendants: true, static: true }, { propertyName: "tagList", first: true, predicate: TagListComponent, descendants: true, static: true }, { propertyName: "popupTemplate", first: true, predicate: ["popupTemplate"], descendants: true, static: true }, { propertyName: "optionsList", first: true, predicate: ["optionsList"], descendants: true }], exportAs: ["kendoMultiSelect"], usesOnChanges: true, ngImport: i0, template: `
|
|
1814
|
-
<ng-container kendoMultiSelectLocalizedMessages
|
|
1815
|
-
i18n-noDataText="kendo.multiselect.noDataText|The text displayed in the popup when there are no items"
|
|
1816
|
-
noDataText="NO DATA FOUND"
|
|
1817
|
-
|
|
1818
|
-
i18n-clearTitle="kendo.multiselect.clearTitle|The title of the clear button"
|
|
1819
|
-
clearTitle="clear"
|
|
1820
|
-
|
|
1821
|
-
i18n-popupLabel="kendo.multiselect.popupLabel|The label of the popup element that contains the list of options when its role is 'region'"
|
|
1822
|
-
popupLabel="Options list"
|
|
1823
|
-
|
|
1824
|
-
i18n-adaptiveCloseButtonTitle="kendo.multiselect.adaptiveCloseButtonTitle|The title of the Close button of the ActionSheet that is rendered instead of the Popup when using small screen devices in adaptive mode."
|
|
1825
|
-
adaptiveCloseButtonTitle="Close"
|
|
1826
|
-
|
|
1827
|
-
i18n-useCustomValueText="kendo.multiselect.useCustomValueText|The text displayed when the user types a custom value that is not in the list of options."
|
|
1828
|
-
useCustomValueText="{{ 'Use "{customValue}"' }}"
|
|
1829
|
-
>
|
|
1830
|
-
</ng-container>
|
|
1831
|
-
|
|
1832
|
-
<ng-container
|
|
1833
|
-
kendoDropDownSharedEvents
|
|
1834
|
-
[hostElement]="hostElement"
|
|
1835
|
-
[(isFocused)]="isFocused"
|
|
1836
|
-
(handleBlur)="handleBlur()"
|
|
1837
|
-
(onFocus)="handleFocus()"
|
|
1838
|
-
>
|
|
1839
|
-
@if (prefixTemplate) {
|
|
1840
|
-
<span class="k-input-prefix k-input-prefix-horizontal">
|
|
1841
|
-
<ng-template [ngTemplateOutlet]="prefixTemplate?.templateRef">
|
|
1842
|
-
</ng-template>
|
|
1843
|
-
</span>
|
|
1844
|
-
}
|
|
1845
|
-
@if (prefixTemplate && prefixTemplate.showSeparator) {
|
|
1846
|
-
<kendo-separator></kendo-separator>
|
|
1847
|
-
}
|
|
1848
|
-
<div class="k-input-values">
|
|
1849
|
-
<kendo-taglist
|
|
1850
|
-
[size]="size"
|
|
1851
|
-
[rounded]="rounded"
|
|
1852
|
-
[fillMode]="fillMode"
|
|
1853
|
-
[id]="tagListId"
|
|
1854
|
-
[tags]="tags"
|
|
1855
|
-
[textField]="textField"
|
|
1856
|
-
[valueField]="valueField"
|
|
1857
|
-
[focused]="focusedTagIndex"
|
|
1858
|
-
[disabled]="disabled"
|
|
1859
|
-
[template]="tagTemplate"
|
|
1860
|
-
[groupTemplate]="groupTagTemplate"
|
|
1861
|
-
[tagPrefix]="tagPrefix"
|
|
1862
|
-
[disabledIndices]="disabledIndices"
|
|
1863
|
-
(removeTag)="handleRemoveTag($event)"
|
|
1864
|
-
>
|
|
1865
|
-
</kendo-taglist>
|
|
1866
|
-
<input
|
|
1867
|
-
kendoSearchbar
|
|
1868
|
-
[ariaControls]="ariaControls"
|
|
1869
|
-
[ariaExpanded]="isOpen"
|
|
1870
|
-
[id]="focusableId"
|
|
1871
|
-
[tagListId]="tagListId"
|
|
1872
|
-
[isLoading]="loading"
|
|
1873
|
-
[isFilterable]="filterable"
|
|
1874
|
-
[activeDescendant]="activeDescendant"
|
|
1875
|
-
[userInput]="text"
|
|
1876
|
-
[disabled]="disabled"
|
|
1877
|
-
[readonly]="readonly || this.isAdaptive"
|
|
1878
|
-
[tabIndex]="tabIndex"
|
|
1879
|
-
[isRequired]="isControlRequired"
|
|
1880
|
-
[placeholder]="placeholder"
|
|
1881
|
-
[inputAttributes]="inputAttributes"
|
|
1882
|
-
(onNavigate)="handleNavigate($event)"
|
|
1883
|
-
(valueChange)="handleFilter($event)"
|
|
1884
|
-
(onBlur)="handleInputBlur()"
|
|
1885
|
-
(onFocus)="handleInputFocus()"
|
|
1886
|
-
(click)="handleClick()"
|
|
1887
|
-
/>
|
|
1888
|
-
</div>
|
|
1889
|
-
|
|
1890
|
-
@if (!loading && !readonly && clearButton && (tags?.length || text?.length)) {
|
|
1891
|
-
<span
|
|
1892
|
-
class="k-clear-value"
|
|
1893
|
-
[style.visibility]="clearButtonVisibility"
|
|
1894
|
-
[attr.title]="messageFor('clearTitle')"
|
|
1895
|
-
role="button"
|
|
1896
|
-
tabindex="-1"
|
|
1897
|
-
(mousedown)="clearAll($event)"
|
|
1898
|
-
>
|
|
1899
|
-
<kendo-icon-wrapper
|
|
1900
|
-
class="k-icon"
|
|
1901
|
-
name="x"
|
|
1902
|
-
[svgIcon]="xIcon"
|
|
1903
|
-
>
|
|
1904
|
-
</kendo-icon-wrapper>
|
|
1905
|
-
</span>
|
|
1906
|
-
}
|
|
1907
|
-
@if (loading) {
|
|
1908
|
-
<span
|
|
1909
|
-
class="k-icon k-i-loading k-input-loading-icon"
|
|
1910
|
-
>
|
|
1911
|
-
</span>
|
|
1912
|
-
}
|
|
1913
|
-
@if (suffixTemplate && suffixTemplate.showSeparator) {
|
|
1914
|
-
<kendo-separator></kendo-separator>
|
|
1915
|
-
}
|
|
1916
|
-
@if (suffixTemplate) {
|
|
1917
|
-
<span class="k-input-suffix k-input-suffix-horizontal">
|
|
1918
|
-
<ng-template [ngTemplateOutlet]="suffixTemplate?.templateRef">
|
|
1919
|
-
</ng-template>
|
|
1920
|
-
</span>
|
|
1921
|
-
}
|
|
1922
|
-
</ng-container>
|
|
1923
|
-
|
|
1924
|
-
<ng-template #popupTemplate>
|
|
1925
|
-
<ng-container *ngTemplateOutlet="sharedPopupActionSheetTemplate"></ng-container>
|
|
1926
|
-
</ng-template>
|
|
1927
|
-
@if (isOpen || isAdaptiveModeEnabled) {
|
|
1928
|
-
<kendo-resize-sensor (resize)="onResize()"></kendo-resize-sensor>
|
|
1929
|
-
}
|
|
1930
|
-
<ng-container #container></ng-container>
|
|
1931
|
-
|
|
1932
|
-
<kendo-adaptive-renderer
|
|
1933
|
-
[sharedPopupActionSheetTemplate]="sharedPopupActionSheetTemplate"
|
|
1934
|
-
[title]="adaptiveTitle"
|
|
1935
|
-
[showTextInput]="true"
|
|
1936
|
-
[subtitle]="adaptiveSubtitle"
|
|
1937
|
-
(closePopup)="applyValue()"
|
|
1938
|
-
(textInputChange)="handleFilter($event)"
|
|
1939
|
-
[placeholder]="placeholder"
|
|
1940
|
-
(navigate)="handleNavigate($event)"
|
|
1941
|
-
[searchBarValue]="text">
|
|
1942
|
-
</kendo-adaptive-renderer>
|
|
1943
|
-
|
|
1944
|
-
<ng-template #sharedPopupActionSheetTemplate>
|
|
1945
|
-
<!--header template-->
|
|
1946
|
-
@if (headerTemplate) {
|
|
1947
|
-
<ng-template
|
|
1948
|
-
[templateContext]="{
|
|
1949
|
-
templateRef: headerTemplate.templateRef
|
|
1950
|
-
}">
|
|
1951
|
-
</ng-template>
|
|
1952
|
-
}
|
|
1953
|
-
<!--list-->
|
|
1954
|
-
<kendo-list
|
|
1955
|
-
#optionsList
|
|
1956
|
-
[size]="isAdaptive ? 'large' : size"
|
|
1957
|
-
[rounded]="rounded"
|
|
1958
|
-
[id]="listBoxId"
|
|
1959
|
-
[optionPrefix]="optionPrefix"
|
|
1960
|
-
[data]="data"
|
|
1961
|
-
[textField]="textField"
|
|
1962
|
-
[valueField]="valueField"
|
|
1963
|
-
[template]="template"
|
|
1964
|
-
[groupTemplate]="groupTemplate"
|
|
1965
|
-
[fixedGroupTemplate]="fixedGroupTemplate"
|
|
1966
|
-
[height]="listHeight"
|
|
1967
|
-
[show]="isOpen"
|
|
1968
|
-
[multipleSelection]="true"
|
|
1969
|
-
[virtual]="virtual"
|
|
1970
|
-
(pageChange)="pageChange($event)"
|
|
1971
|
-
[checkboxes]="checkboxes"
|
|
1972
|
-
[isMultiselect]="true"
|
|
1973
|
-
[isActionSheetExpanded]="isActionSheetExpanded"
|
|
1974
|
-
[showStickyHeader]="showStickyHeader"
|
|
1975
|
-
[customItemTemplate]="customItemTemplate"
|
|
1976
|
-
[text]="text"
|
|
1977
|
-
[allowCustom]="allowCustom"
|
|
1978
|
-
>
|
|
1979
|
-
</kendo-list>
|
|
1980
|
-
<!--no data template-->
|
|
1981
|
-
@if (data.length === 0) {
|
|
1982
|
-
<div class="k-no-data">
|
|
1983
|
-
@if (noDataTemplate) {
|
|
1984
|
-
<ng-template
|
|
1985
|
-
[templateContext]="{
|
|
1986
|
-
templateRef: noDataTemplate ? noDataTemplate.templateRef : undefined
|
|
1987
|
-
}">
|
|
1988
|
-
</ng-template>
|
|
1989
|
-
}
|
|
1990
|
-
@if (!noDataTemplate) {
|
|
1991
|
-
<div>{{ messageFor('noDataText') }}</div>
|
|
1992
|
-
}
|
|
1993
|
-
</div>
|
|
1994
|
-
}
|
|
1995
|
-
<!--footer template-->
|
|
1996
|
-
@if (footerTemplate) {
|
|
1997
|
-
<ng-template
|
|
1998
|
-
[templateContext]="{
|
|
1999
|
-
templateRef: footerTemplate.templateRef
|
|
2000
|
-
}">
|
|
2001
|
-
</ng-template>
|
|
2002
|
-
}
|
|
2003
|
-
</ng-template>
|
|
2004
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "\n [kendoDropDownListLocalizedMessages],\n [kendoDropDownTreeLocalizedMessages],\n [kendoComboBoxLocalizedMessages],\n [kendoMultiColumnComboBoxLocalizedMessages],\n [kendoAutoCompleteLocalizedMessages],\n [kendoMultiSelectLocalizedMessages],\n [kendoMultiSelectTreeLocalizedMessages]\n " }, { kind: "directive", type: SharedDropDownEventsDirective, selector: "[kendoDropDownSharedEvents]", inputs: ["hostElement", "clearButtonClicked", "isFocused"], outputs: ["isFocusedChange", "onFocus", "handleBlur"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: SeparatorComponent, selector: "kendo-separator", inputs: ["orientation"] }, { kind: "component", type: TagListComponent, selector: "kendo-taglist", inputs: ["tags", "textField", "valueField", "valueDepth", "focused", "template", "groupTemplate", "disabled", "tagPrefix", "id", "size", "rounded", "fillMode", "disabledIndices"], outputs: ["removeTag"] }, { kind: "component", type: SearchBarComponent, selector: "input[kendoSearchbar]", inputs: ["tagListId", "readonly", "disabled", "isRequired", "isSuggestable", "isFilterable", "userInput", "suggestedText", "inputAttributes", "id", "activeDescendant", "tabIndex", "isLoading", "ariaControls", "ariaExpanded", "placeholder"], outputs: ["valueChange", "onBlur", "onFocus", "onClick", "onNavigate"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }, { kind: "component", type: ResizeSensorComponent, selector: "kendo-resize-sensor", inputs: ["rateLimit"], outputs: ["resize"] }, { kind: "component", type: AdaptiveRendererComponent, selector: "kendo-adaptive-renderer", inputs: ["title", "subtitle", "showTextInput", "sharedPopupActionSheetTemplate", "text", "placeholder", "searchBarValue", "filterable"], outputs: ["closePopup", "textInputChange", "navigate", "onExpand"] }, { kind: "directive", type: TemplateContextDirective, selector: "[templateContext]", inputs: ["templateContext"] }, { kind: "component", type: ListComponent, selector: "kendo-list", inputs: ["selected", "focused", "textField", "valueField", "height", "template", "groupTemplate", "fixedGroupTemplate", "show", "id", "optionPrefix", "multipleSelection", "virtual", "type", "checkboxes", "ariaLive", "isMultiselect", "isActionSheetExpanded", "showStickyHeader", "rowWidth", "customItemTemplate", "text", "allowCustom", "defaultItem", "data", "size", "rounded"], outputs: ["onClick", "pageChange", "listResize", "popupListScroll"] }] });
|
|
2005
|
-
}
|
|
2006
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MultiSelectComponent, decorators: [{
|
|
2007
|
-
type: Component,
|
|
2008
|
-
args: [{
|
|
2009
|
-
exportAs: 'kendoMultiSelect',
|
|
2010
|
-
providers: [
|
|
2011
|
-
MULTISELECT_VALUE_ACCESSOR,
|
|
2012
|
-
DataService,
|
|
2013
|
-
SelectionService,
|
|
2014
|
-
NavigationService,
|
|
2015
|
-
DisabledItemsService,
|
|
2016
|
-
LocalizationService,
|
|
2017
|
-
{
|
|
2018
|
-
provide: L10N_PREFIX,
|
|
2019
|
-
useValue: 'kendo.multiselect'
|
|
2020
|
-
},
|
|
2021
|
-
{
|
|
2022
|
-
provide: FilterableComponent, useExisting: forwardRef(() => MultiSelectComponent)
|
|
2023
|
-
},
|
|
2024
|
-
{
|
|
2025
|
-
provide: KendoInput, useExisting: forwardRef(() => MultiSelectComponent)
|
|
2026
|
-
}
|
|
2027
|
-
],
|
|
2028
|
-
selector: 'kendo-multiselect',
|
|
2029
|
-
template: `
|
|
2030
|
-
<ng-container kendoMultiSelectLocalizedMessages
|
|
2031
|
-
i18n-noDataText="kendo.multiselect.noDataText|The text displayed in the popup when there are no items"
|
|
2032
|
-
noDataText="NO DATA FOUND"
|
|
2033
|
-
|
|
2034
|
-
i18n-clearTitle="kendo.multiselect.clearTitle|The title of the clear button"
|
|
2035
|
-
clearTitle="clear"
|
|
2036
|
-
|
|
2037
|
-
i18n-popupLabel="kendo.multiselect.popupLabel|The label of the popup element that contains the list of options when its role is 'region'"
|
|
2038
|
-
popupLabel="Options list"
|
|
2039
|
-
|
|
2040
|
-
i18n-adaptiveCloseButtonTitle="kendo.multiselect.adaptiveCloseButtonTitle|The title of the Close button of the ActionSheet that is rendered instead of the Popup when using small screen devices in adaptive mode."
|
|
2041
|
-
adaptiveCloseButtonTitle="Close"
|
|
2042
|
-
|
|
2043
|
-
i18n-useCustomValueText="kendo.multiselect.useCustomValueText|The text displayed when the user types a custom value that is not in the list of options."
|
|
2044
|
-
useCustomValueText="{{ 'Use "{customValue}"' }}"
|
|
2045
|
-
>
|
|
2046
|
-
</ng-container>
|
|
2047
|
-
|
|
2048
|
-
<ng-container
|
|
2049
|
-
kendoDropDownSharedEvents
|
|
2050
|
-
[hostElement]="hostElement"
|
|
2051
|
-
[(isFocused)]="isFocused"
|
|
2052
|
-
(handleBlur)="handleBlur()"
|
|
2053
|
-
(onFocus)="handleFocus()"
|
|
2054
|
-
>
|
|
2055
|
-
@if (prefixTemplate) {
|
|
2056
|
-
<span class="k-input-prefix k-input-prefix-horizontal">
|
|
2057
|
-
<ng-template [ngTemplateOutlet]="prefixTemplate?.templateRef">
|
|
2058
|
-
</ng-template>
|
|
2059
|
-
</span>
|
|
2060
|
-
}
|
|
2061
|
-
@if (prefixTemplate && prefixTemplate.showSeparator) {
|
|
2062
|
-
<kendo-separator></kendo-separator>
|
|
2063
|
-
}
|
|
2064
|
-
<div class="k-input-values">
|
|
2065
|
-
<kendo-taglist
|
|
2066
|
-
[size]="size"
|
|
2067
|
-
[rounded]="rounded"
|
|
2068
|
-
[fillMode]="fillMode"
|
|
2069
|
-
[id]="tagListId"
|
|
2070
|
-
[tags]="tags"
|
|
2071
|
-
[textField]="textField"
|
|
2072
|
-
[valueField]="valueField"
|
|
2073
|
-
[focused]="focusedTagIndex"
|
|
2074
|
-
[disabled]="disabled"
|
|
2075
|
-
[template]="tagTemplate"
|
|
2076
|
-
[groupTemplate]="groupTagTemplate"
|
|
2077
|
-
[tagPrefix]="tagPrefix"
|
|
2078
|
-
[disabledIndices]="disabledIndices"
|
|
2079
|
-
(removeTag)="handleRemoveTag($event)"
|
|
2080
|
-
>
|
|
2081
|
-
</kendo-taglist>
|
|
2082
|
-
<input
|
|
2083
|
-
kendoSearchbar
|
|
2084
|
-
[ariaControls]="ariaControls"
|
|
2085
|
-
[ariaExpanded]="isOpen"
|
|
2086
|
-
[id]="focusableId"
|
|
2087
|
-
[tagListId]="tagListId"
|
|
2088
|
-
[isLoading]="loading"
|
|
2089
|
-
[isFilterable]="filterable"
|
|
2090
|
-
[activeDescendant]="activeDescendant"
|
|
2091
|
-
[userInput]="text"
|
|
2092
|
-
[disabled]="disabled"
|
|
2093
|
-
[readonly]="readonly || this.isAdaptive"
|
|
2094
|
-
[tabIndex]="tabIndex"
|
|
2095
|
-
[isRequired]="isControlRequired"
|
|
2096
|
-
[placeholder]="placeholder"
|
|
2097
|
-
[inputAttributes]="inputAttributes"
|
|
2098
|
-
(onNavigate)="handleNavigate($event)"
|
|
2099
|
-
(valueChange)="handleFilter($event)"
|
|
2100
|
-
(onBlur)="handleInputBlur()"
|
|
2101
|
-
(onFocus)="handleInputFocus()"
|
|
2102
|
-
(click)="handleClick()"
|
|
2103
|
-
/>
|
|
2104
|
-
</div>
|
|
2105
|
-
|
|
2106
|
-
@if (!loading && !readonly && clearButton && (tags?.length || text?.length)) {
|
|
2107
|
-
<span
|
|
2108
|
-
class="k-clear-value"
|
|
2109
|
-
[style.visibility]="clearButtonVisibility"
|
|
2110
|
-
[attr.title]="messageFor('clearTitle')"
|
|
2111
|
-
role="button"
|
|
2112
|
-
tabindex="-1"
|
|
2113
|
-
(mousedown)="clearAll($event)"
|
|
2114
|
-
>
|
|
2115
|
-
<kendo-icon-wrapper
|
|
2116
|
-
class="k-icon"
|
|
2117
|
-
name="x"
|
|
2118
|
-
[svgIcon]="xIcon"
|
|
2119
|
-
>
|
|
2120
|
-
</kendo-icon-wrapper>
|
|
2121
|
-
</span>
|
|
2122
|
-
}
|
|
2123
|
-
@if (loading) {
|
|
2124
|
-
<span
|
|
2125
|
-
class="k-icon k-i-loading k-input-loading-icon"
|
|
2126
|
-
>
|
|
2127
|
-
</span>
|
|
2128
|
-
}
|
|
2129
|
-
@if (suffixTemplate && suffixTemplate.showSeparator) {
|
|
2130
|
-
<kendo-separator></kendo-separator>
|
|
2131
|
-
}
|
|
2132
|
-
@if (suffixTemplate) {
|
|
2133
|
-
<span class="k-input-suffix k-input-suffix-horizontal">
|
|
2134
|
-
<ng-template [ngTemplateOutlet]="suffixTemplate?.templateRef">
|
|
2135
|
-
</ng-template>
|
|
2136
|
-
</span>
|
|
2137
|
-
}
|
|
2138
|
-
</ng-container>
|
|
2139
|
-
|
|
2140
|
-
<ng-template #popupTemplate>
|
|
2141
|
-
<ng-container *ngTemplateOutlet="sharedPopupActionSheetTemplate"></ng-container>
|
|
2142
|
-
</ng-template>
|
|
2143
|
-
@if (isOpen || isAdaptiveModeEnabled) {
|
|
2144
|
-
<kendo-resize-sensor (resize)="onResize()"></kendo-resize-sensor>
|
|
2145
|
-
}
|
|
2146
|
-
<ng-container #container></ng-container>
|
|
2147
|
-
|
|
2148
|
-
<kendo-adaptive-renderer
|
|
2149
|
-
[sharedPopupActionSheetTemplate]="sharedPopupActionSheetTemplate"
|
|
2150
|
-
[title]="adaptiveTitle"
|
|
2151
|
-
[showTextInput]="true"
|
|
2152
|
-
[subtitle]="adaptiveSubtitle"
|
|
2153
|
-
(closePopup)="applyValue()"
|
|
2154
|
-
(textInputChange)="handleFilter($event)"
|
|
2155
|
-
[placeholder]="placeholder"
|
|
2156
|
-
(navigate)="handleNavigate($event)"
|
|
2157
|
-
[searchBarValue]="text">
|
|
2158
|
-
</kendo-adaptive-renderer>
|
|
2159
|
-
|
|
2160
|
-
<ng-template #sharedPopupActionSheetTemplate>
|
|
2161
|
-
<!--header template-->
|
|
2162
|
-
@if (headerTemplate) {
|
|
2163
|
-
<ng-template
|
|
2164
|
-
[templateContext]="{
|
|
2165
|
-
templateRef: headerTemplate.templateRef
|
|
2166
|
-
}">
|
|
2167
|
-
</ng-template>
|
|
2168
|
-
}
|
|
2169
|
-
<!--list-->
|
|
2170
|
-
<kendo-list
|
|
2171
|
-
#optionsList
|
|
2172
|
-
[size]="isAdaptive ? 'large' : size"
|
|
2173
|
-
[rounded]="rounded"
|
|
2174
|
-
[id]="listBoxId"
|
|
2175
|
-
[optionPrefix]="optionPrefix"
|
|
2176
|
-
[data]="data"
|
|
2177
|
-
[textField]="textField"
|
|
2178
|
-
[valueField]="valueField"
|
|
2179
|
-
[template]="template"
|
|
2180
|
-
[groupTemplate]="groupTemplate"
|
|
2181
|
-
[fixedGroupTemplate]="fixedGroupTemplate"
|
|
2182
|
-
[height]="listHeight"
|
|
2183
|
-
[show]="isOpen"
|
|
2184
|
-
[multipleSelection]="true"
|
|
2185
|
-
[virtual]="virtual"
|
|
2186
|
-
(pageChange)="pageChange($event)"
|
|
2187
|
-
[checkboxes]="checkboxes"
|
|
2188
|
-
[isMultiselect]="true"
|
|
2189
|
-
[isActionSheetExpanded]="isActionSheetExpanded"
|
|
2190
|
-
[showStickyHeader]="showStickyHeader"
|
|
2191
|
-
[customItemTemplate]="customItemTemplate"
|
|
2192
|
-
[text]="text"
|
|
2193
|
-
[allowCustom]="allowCustom"
|
|
2194
|
-
>
|
|
2195
|
-
</kendo-list>
|
|
2196
|
-
<!--no data template-->
|
|
2197
|
-
@if (data.length === 0) {
|
|
2198
|
-
<div class="k-no-data">
|
|
2199
|
-
@if (noDataTemplate) {
|
|
2200
|
-
<ng-template
|
|
2201
|
-
[templateContext]="{
|
|
2202
|
-
templateRef: noDataTemplate ? noDataTemplate.templateRef : undefined
|
|
2203
|
-
}">
|
|
2204
|
-
</ng-template>
|
|
2205
|
-
}
|
|
2206
|
-
@if (!noDataTemplate) {
|
|
2207
|
-
<div>{{ messageFor('noDataText') }}</div>
|
|
2208
|
-
}
|
|
2209
|
-
</div>
|
|
2210
|
-
}
|
|
2211
|
-
<!--footer template-->
|
|
2212
|
-
@if (footerTemplate) {
|
|
2213
|
-
<ng-template
|
|
2214
|
-
[templateContext]="{
|
|
2215
|
-
templateRef: footerTemplate.templateRef
|
|
2216
|
-
}">
|
|
2217
|
-
</ng-template>
|
|
2218
|
-
}
|
|
2219
|
-
</ng-template>
|
|
2220
|
-
`,
|
|
2221
|
-
standalone: true,
|
|
2222
|
-
imports: [LocalizedMessagesDirective, SharedDropDownEventsDirective, NgTemplateOutlet, SeparatorComponent, TagListComponent, SearchBarComponent, IconWrapperComponent, ResizeSensorComponent, AdaptiveRendererComponent, TemplateContextDirective, ListComponent]
|
|
2223
|
-
}]
|
|
2224
|
-
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.LocalizationService }, { type: i2.PopupService }, { type: i3.DataService }, { type: i4.SelectionService }, { type: i5.NavigationService }, { type: i6.DisabledItemsService }, { type: i0.ChangeDetectorRef }, { type: i0.KeyValueDiffers }, { type: i0.Renderer2 }, { type: i0.NgZone }, { type: i0.Injector }, { type: i0.ElementRef }, { type: i7.AdaptiveService }], propDecorators: { adaptiveRendererComponent: [{
|
|
2225
|
-
type: ViewChild,
|
|
2226
|
-
args: [AdaptiveRendererComponent]
|
|
2227
|
-
}], showStickyHeader: [{
|
|
2228
|
-
type: Input
|
|
2229
|
-
}], focusableId: [{
|
|
2230
|
-
type: Input
|
|
2231
|
-
}], autoClose: [{
|
|
2232
|
-
type: Input
|
|
2233
|
-
}], loading: [{
|
|
2234
|
-
type: Input
|
|
2235
|
-
}], data: [{
|
|
2236
|
-
type: Input
|
|
2237
|
-
}], value: [{
|
|
2238
|
-
type: Input
|
|
2239
|
-
}], valueField: [{
|
|
2240
|
-
type: Input
|
|
2241
|
-
}], textField: [{
|
|
2242
|
-
type: Input
|
|
2243
|
-
}], tabindex: [{
|
|
2244
|
-
type: Input
|
|
2245
|
-
}], tabIndex: [{
|
|
2246
|
-
type: Input,
|
|
2247
|
-
args: ["tabIndex"]
|
|
2248
|
-
}], size: [{
|
|
2249
|
-
type: Input
|
|
2250
|
-
}], rounded: [{
|
|
2251
|
-
type: Input
|
|
2252
|
-
}], fillMode: [{
|
|
2253
|
-
type: Input
|
|
2254
|
-
}], placeholder: [{
|
|
2255
|
-
type: Input
|
|
2256
|
-
}], adaptiveMode: [{
|
|
2257
|
-
type: Input
|
|
2258
|
-
}], adaptiveTitle: [{
|
|
2259
|
-
type: Input
|
|
2260
|
-
}], adaptiveSubtitle: [{
|
|
2261
|
-
type: Input
|
|
2262
|
-
}], disabled: [{
|
|
2263
|
-
type: Input
|
|
2264
|
-
}], itemDisabled: [{
|
|
2265
|
-
type: Input
|
|
2266
|
-
}], checkboxes: [{
|
|
2267
|
-
type: Input
|
|
2268
|
-
}], readonly: [{
|
|
2269
|
-
type: Input
|
|
2270
|
-
}, {
|
|
2271
|
-
type: HostBinding,
|
|
2272
|
-
args: ['class.k-readonly']
|
|
2273
|
-
}], filterable: [{
|
|
2274
|
-
type: Input
|
|
2275
|
-
}], virtual: [{
|
|
2276
|
-
type: Input
|
|
2277
|
-
}], popupSettings: [{
|
|
2278
|
-
type: Input
|
|
2279
|
-
}], listHeight: [{
|
|
2280
|
-
type: Input
|
|
2281
|
-
}], valuePrimitive: [{
|
|
2282
|
-
type: Input
|
|
2283
|
-
}], clearButton: [{
|
|
2284
|
-
type: Input
|
|
2285
|
-
}], tagMapper: [{
|
|
2286
|
-
type: Input
|
|
2287
|
-
}], allowCustom: [{
|
|
2288
|
-
type: Input
|
|
2289
|
-
}], valueNormalizer: [{
|
|
2290
|
-
type: Input
|
|
2291
|
-
}], inputAttributes: [{
|
|
2292
|
-
type: Input
|
|
2293
|
-
}], filterChange: [{
|
|
2294
|
-
type: Output
|
|
2295
|
-
}], valueChange: [{
|
|
2296
|
-
type: Output
|
|
2297
|
-
}], open: [{
|
|
2298
|
-
type: Output
|
|
2299
|
-
}], opened: [{
|
|
2300
|
-
type: Output
|
|
2301
|
-
}], close: [{
|
|
2302
|
-
type: Output
|
|
2303
|
-
}], closed: [{
|
|
2304
|
-
type: Output
|
|
2305
|
-
}], onFocus: [{
|
|
2306
|
-
type: Output,
|
|
2307
|
-
args: ['focus']
|
|
2308
|
-
}], onBlur: [{
|
|
2309
|
-
type: Output,
|
|
2310
|
-
args: ['blur']
|
|
2311
|
-
}], inputFocus: [{
|
|
2312
|
-
type: Output
|
|
2313
|
-
}], inputBlur: [{
|
|
2314
|
-
type: Output
|
|
2315
|
-
}], removeTag: [{
|
|
2316
|
-
type: Output
|
|
2317
|
-
}], container: [{
|
|
2318
|
-
type: ViewChild,
|
|
2319
|
-
args: ['container', { read: ViewContainerRef, static: true }]
|
|
2320
|
-
}], searchbar: [{
|
|
2321
|
-
type: ViewChild,
|
|
2322
|
-
args: [SearchBarComponent, { static: true }]
|
|
2323
|
-
}], tagList: [{
|
|
2324
|
-
type: ViewChild,
|
|
2325
|
-
args: [TagListComponent, { static: true }]
|
|
2326
|
-
}], popupTemplate: [{
|
|
2327
|
-
type: ViewChild,
|
|
2328
|
-
args: ['popupTemplate', { static: true }]
|
|
2329
|
-
}], optionsList: [{
|
|
2330
|
-
type: ViewChild,
|
|
2331
|
-
args: ['optionsList', { static: false }]
|
|
2332
|
-
}], template: [{
|
|
2333
|
-
type: ContentChild,
|
|
2334
|
-
args: [ItemTemplateDirective, { static: false }]
|
|
2335
|
-
}], customItemTemplate: [{
|
|
2336
|
-
type: ContentChild,
|
|
2337
|
-
args: [CustomItemTemplateDirective, { static: false }]
|
|
2338
|
-
}], groupTemplate: [{
|
|
2339
|
-
type: ContentChild,
|
|
2340
|
-
args: [GroupTemplateDirective, { static: false }]
|
|
2341
|
-
}], fixedGroupTemplate: [{
|
|
2342
|
-
type: ContentChild,
|
|
2343
|
-
args: [FixedGroupTemplateDirective, { static: false }]
|
|
2344
|
-
}], headerTemplate: [{
|
|
2345
|
-
type: ContentChild,
|
|
2346
|
-
args: [HeaderTemplateDirective, { static: false }]
|
|
2347
|
-
}], footerTemplate: [{
|
|
2348
|
-
type: ContentChild,
|
|
2349
|
-
args: [FooterTemplateDirective, { static: false }]
|
|
2350
|
-
}], tagTemplate: [{
|
|
2351
|
-
type: ContentChild,
|
|
2352
|
-
args: [TagTemplateDirective, { static: false }]
|
|
2353
|
-
}], groupTagTemplate: [{
|
|
2354
|
-
type: ContentChild,
|
|
2355
|
-
args: [GroupTagTemplateDirective, { static: false }]
|
|
2356
|
-
}], noDataTemplate: [{
|
|
2357
|
-
type: ContentChild,
|
|
2358
|
-
args: [NoDataTemplateDirective, { static: false }]
|
|
2359
|
-
}], suffixTemplate: [{
|
|
2360
|
-
type: ContentChild,
|
|
2361
|
-
args: [SuffixTemplateDirective]
|
|
2362
|
-
}], prefixTemplate: [{
|
|
2363
|
-
type: ContentChild,
|
|
2364
|
-
args: [PrefixTemplateDirective]
|
|
2365
|
-
}], hostClasses: [{
|
|
2366
|
-
type: HostBinding,
|
|
2367
|
-
args: ['class.k-multiselect']
|
|
2368
|
-
}, {
|
|
2369
|
-
type: HostBinding,
|
|
2370
|
-
args: ['class.k-input']
|
|
2371
|
-
}], dir: [{
|
|
2372
|
-
type: HostBinding,
|
|
2373
|
-
args: ['attr.dir']
|
|
2374
|
-
}], disabledClass: [{
|
|
2375
|
-
type: HostBinding,
|
|
2376
|
-
args: ['class.k-disabled']
|
|
2377
|
-
}], isLoading: [{
|
|
2378
|
-
type: HostBinding,
|
|
2379
|
-
args: ['class.k-loading']
|
|
2380
|
-
}] } });
|