@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,2359 +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 { ChangeDetectorRef, Component, ContentChild, ElementRef, EventEmitter, forwardRef, HostBinding, Injector, Input, isDevMode, NgZone, Output, Renderer2, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core';
|
|
6
|
-
import { NgControl, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
7
|
-
import { anyChanged, guid, hasObservers, Keys, KendoInput, isDocumentAvailable, EventsOutsideAngularDirective, ResizeSensorComponent, TemplateContextDirective, normalizeKeys, parseCSSClassNames } from '@progress/kendo-angular-common';
|
|
8
|
-
import { AdaptiveService } from '@progress/kendo-angular-utils';
|
|
9
|
-
import { L10N_PREFIX, LocalizationService } from '@progress/kendo-angular-l10n';
|
|
10
|
-
import { NavigationService } from '../common/navigation/navigation.service';
|
|
11
|
-
import { PopupService } from '@progress/kendo-angular-popup';
|
|
12
|
-
import { DataBoundComponent, ExpandableComponent, TreeViewComponent } from '@progress/kendo-angular-treeview';
|
|
13
|
-
import { DataService } from '../common/data.service';
|
|
14
|
-
import { DisabledItemsService } from '../common/disabled-items/disabled-items.service';
|
|
15
|
-
import { SelectionService } from '../common/selection/selection.service';
|
|
16
|
-
import { PreventableEvent } from '../common/models/preventable-event';
|
|
17
|
-
import { NavigationAction } from '../common/navigation/navigation-action';
|
|
18
|
-
import { RemoveTagEvent } from '../common/models/remove-tag-event';
|
|
19
|
-
import { MultiSelectTreeMessages } from '../common/constants/error-messages';
|
|
20
|
-
import { animationDuration, fetchDescendentNodes, getFillModeClass, getRoundedClass, getSearchableItems, getSizeClass, hasProps, isArray, isLetter, isObject, isObjectArray, isPresent, isTruthy, isUntouched, noop, parseNumber, setActionSheetTitle, valueFrom } from '../common/util';
|
|
21
|
-
import { HeaderTemplateDirective } from '../common/templates/header-template.directive';
|
|
22
|
-
import { FooterTemplateDirective } from '../common/templates/footer-template.directive';
|
|
23
|
-
import { NodeTemplateDirective } from './templates/node-template.directive';
|
|
24
|
-
import { NoDataTemplateDirective } from '../common/templates/no-data-template.directive';
|
|
25
|
-
import { TagTemplateDirective } from '../common/templates/tag-template.directive';
|
|
26
|
-
import { GroupTagTemplateDirective } from '../common/templates/group-tag-template.directive';
|
|
27
|
-
import { merge, of, Subject, Subscription } from 'rxjs';
|
|
28
|
-
import { debounceTime, filter, tap } from 'rxjs/operators';
|
|
29
|
-
import { buildTreeItem, MultiSelectTreeLookupService, nodeIndex } from './lookup/lookup.service';
|
|
30
|
-
import { searchIcon, xIcon } from '@progress/kendo-svg-icons';
|
|
31
|
-
import { AdaptiveRendererComponent } from '../common/adaptive-renderer.component';
|
|
32
|
-
import { CheckDirective } from './checked-state/check.directive';
|
|
33
|
-
import { CheckAllDirective } from './checked-state/check-all.directive';
|
|
34
|
-
import { FilterInputDirective } from '../common/filter-input.directive';
|
|
35
|
-
import { NgTemplateOutlet, NgClass } from '@angular/common';
|
|
36
|
-
import { TagListComponent } from '../common/taglist.component';
|
|
37
|
-
import { LocalizedMessagesDirective } from '../common/localization/localized-messages.directive';
|
|
38
|
-
import { IconWrapperComponent } from '@progress/kendo-angular-icons';
|
|
39
|
-
import { touchEnabled } from '@progress/kendo-common';
|
|
40
|
-
import * as i0 from "@angular/core";
|
|
41
|
-
import * as i1 from "@progress/kendo-angular-popup";
|
|
42
|
-
import * as i2 from "../common/navigation/navigation.service";
|
|
43
|
-
import * as i3 from "@progress/kendo-angular-l10n";
|
|
44
|
-
import * as i4 from "./lookup/lookup.service";
|
|
45
|
-
import * as i5 from "@progress/kendo-angular-utils";
|
|
46
|
-
const DEFAULT_POPUP_SETTINGS = { animate: true };
|
|
47
|
-
const DEFAULT_CHECKABLE_SETTINGS = { checkChildren: true, checkOnClick: true };
|
|
48
|
-
const hasChildren = () => false;
|
|
49
|
-
const fetchChildren = () => of([]);
|
|
50
|
-
const itemDisabled = () => false;
|
|
51
|
-
const isNodeVisible = () => true;
|
|
52
|
-
const DEFAULT_SIZE = 'medium';
|
|
53
|
-
const DEFAULT_ROUNDED = 'medium';
|
|
54
|
-
const DEFAULT_FILL_MODE = 'solid';
|
|
55
|
-
/**
|
|
56
|
-
* Represents the Kendo UI for Angular [MultiSelectTree]({% slug overview_multiselecttree %}) component.
|
|
57
|
-
*
|
|
58
|
-
* The `MultiSelectTree` lets you select multiple items from hierarchical data in a tree structure.
|
|
59
|
-
* It provides built-in filtering, checkboxes, and adaptive rendering for mobile devices.
|
|
60
|
-
*
|
|
61
|
-
* @example
|
|
62
|
-
* ```typescript
|
|
63
|
-
* @Component({
|
|
64
|
-
* selector: 'my-app',
|
|
65
|
-
* template: `
|
|
66
|
-
* <kendo-multiselecttree
|
|
67
|
-
* [data]="data"
|
|
68
|
-
* textField="text"
|
|
69
|
-
* valueField="value"
|
|
70
|
-
* [(value)]="selectedValues">
|
|
71
|
-
* </kendo-multiselecttree>
|
|
72
|
-
* `
|
|
73
|
-
* })
|
|
74
|
-
* export class AppComponent {
|
|
75
|
-
* public data = [
|
|
76
|
-
* { text: 'Root', value: 1, items: [
|
|
77
|
-
* { text: 'Child 1', value: 2 },
|
|
78
|
-
* { text: 'Child 2', value: 3 }
|
|
79
|
-
* ]}
|
|
80
|
-
* ];
|
|
81
|
-
* public selectedValues = [2, 3];
|
|
82
|
-
* }
|
|
83
|
-
* ```
|
|
84
|
-
* @remarks
|
|
85
|
-
* Supported children components are: {@link CustomMessagesComponent}.
|
|
86
|
-
*/
|
|
87
|
-
export class MultiSelectTreeComponent {
|
|
88
|
-
injector;
|
|
89
|
-
wrapper;
|
|
90
|
-
popupService;
|
|
91
|
-
renderer;
|
|
92
|
-
navigationService;
|
|
93
|
-
_zone;
|
|
94
|
-
localization;
|
|
95
|
-
cdr;
|
|
96
|
-
lookup;
|
|
97
|
-
adaptiveService;
|
|
98
|
-
/**
|
|
99
|
-
* @hidden
|
|
100
|
-
*/
|
|
101
|
-
touchEnabled = touchEnabled;
|
|
102
|
-
/**
|
|
103
|
-
* @hidden
|
|
104
|
-
*/
|
|
105
|
-
animationDuration = animationDuration;
|
|
106
|
-
/**
|
|
107
|
-
* @hidden
|
|
108
|
-
*/
|
|
109
|
-
searchIcon = searchIcon;
|
|
110
|
-
/**
|
|
111
|
-
* @hidden
|
|
112
|
-
*/
|
|
113
|
-
xIcon = xIcon;
|
|
114
|
-
hostClasses = true;
|
|
115
|
-
get isDisabled() {
|
|
116
|
-
return this.disabled || null;
|
|
117
|
-
}
|
|
118
|
-
treeViewId = `k-${guid()}`;
|
|
119
|
-
get hostAriaAutocomplete() {
|
|
120
|
-
return this.filterable ? 'list' : null;
|
|
121
|
-
}
|
|
122
|
-
get isLoading() {
|
|
123
|
-
return this.loading;
|
|
124
|
-
}
|
|
125
|
-
get hostAriaInvalid() {
|
|
126
|
-
return this.formControl?.invalid ? true : null;
|
|
127
|
-
}
|
|
128
|
-
get isBusy() {
|
|
129
|
-
return this.loading ? 'true' : null;
|
|
130
|
-
}
|
|
131
|
-
get id() {
|
|
132
|
-
return this.focusableId;
|
|
133
|
-
}
|
|
134
|
-
direction;
|
|
135
|
-
get hostTabIndex() {
|
|
136
|
-
return this.tabindex;
|
|
137
|
-
}
|
|
138
|
-
role = 'combobox';
|
|
139
|
-
ariaHasPopup = 'tree';
|
|
140
|
-
get isReadonly() {
|
|
141
|
-
return this.readonly ? '' : null;
|
|
142
|
-
}
|
|
143
|
-
get ariaDescribedBy() {
|
|
144
|
-
return this.tagListId;
|
|
145
|
-
}
|
|
146
|
-
get ariaActiveDescendant() {
|
|
147
|
-
return this.focusedTagId;
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* @hidden
|
|
151
|
-
*/
|
|
152
|
-
get formControl() {
|
|
153
|
-
const ngControl = this.injector.get(NgControl, null);
|
|
154
|
-
return ngControl?.control || null;
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* @hidden
|
|
158
|
-
*/
|
|
159
|
-
onFilterChange(text) {
|
|
160
|
-
if (this.filterable) {
|
|
161
|
-
this.filter = text;
|
|
162
|
-
this.filterChange.emit(text);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Controls the adaptive mode behavior of the component.
|
|
167
|
-
* Set to `auto` to enable automatic adaptive rendering on small screens.
|
|
168
|
-
*
|
|
169
|
-
* @default 'none'
|
|
170
|
-
*/
|
|
171
|
-
adaptiveMode = 'none';
|
|
172
|
-
/**
|
|
173
|
-
* Sets the title text for the ActionSheet in adaptive mode on small screens.
|
|
174
|
-
* Uses the component label by default if not set.
|
|
175
|
-
*
|
|
176
|
-
* @default ''
|
|
177
|
-
*/
|
|
178
|
-
adaptiveTitle = '';
|
|
179
|
-
/**
|
|
180
|
-
* Sets the subtitle text for the ActionSheet in adaptive mode on small screens.
|
|
181
|
-
* No subtitle appears by default.
|
|
182
|
-
*/
|
|
183
|
-
adaptiveSubtitle;
|
|
184
|
-
/**
|
|
185
|
-
* @hidden
|
|
186
|
-
*/
|
|
187
|
-
get isAdaptiveModeEnabled() {
|
|
188
|
-
return this.adaptiveMode === 'auto';
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* @hidden
|
|
192
|
-
*/
|
|
193
|
-
windowSize = 'large';
|
|
194
|
-
/**
|
|
195
|
-
* @hidden
|
|
196
|
-
*/
|
|
197
|
-
get isActionSheetExpanded() {
|
|
198
|
-
return this.actionSheet?.expanded;
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* @hidden
|
|
202
|
-
*/
|
|
203
|
-
handleKeydown(event, input) {
|
|
204
|
-
const code = normalizeKeys(event);
|
|
205
|
-
if (event.target === this.filterInput?.nativeElement &&
|
|
206
|
-
(code === Keys.ArrowLeft || code === Keys.ArrowRight)) {
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
if (input) {
|
|
210
|
-
event.stopImmediatePropagation();
|
|
211
|
-
}
|
|
212
|
-
const deleteTag = this.isWrapperActive && code === Keys.Backspace && this.tags.length > 0;
|
|
213
|
-
if (deleteTag) {
|
|
214
|
-
this.handleBackspace();
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
if (this.disabled || this.readonly) {
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
if (!this.isFilterActive && isLetter(event.key) && !this.actionSheetSearchBar?.onFocus) {
|
|
221
|
-
this.printableCharacters.next(event.key);
|
|
222
|
-
}
|
|
223
|
-
const eventData = event;
|
|
224
|
-
const action = this.navigationService.process({
|
|
225
|
-
originalEvent: eventData,
|
|
226
|
-
openOnSpace: !this.isOpen,
|
|
227
|
-
closeOnSpace: false
|
|
228
|
-
});
|
|
229
|
-
if (action === NavigationAction.Open) {
|
|
230
|
-
eventData.preventDefault();
|
|
231
|
-
}
|
|
232
|
-
if (this.isOpen && action === NavigationAction.Enter) {
|
|
233
|
-
const spaceKeyDownEvent = new KeyboardEvent('keydown', { 'key': ' ', 'code': 'Space', 'keyCode': 32, 'which': 32 });
|
|
234
|
-
this.treeview?.element.nativeElement.dispatchEvent(spaceKeyDownEvent);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* @hidden
|
|
239
|
-
*/
|
|
240
|
-
adaptiveRendererComponent;
|
|
241
|
-
/**
|
|
242
|
-
* @hidden
|
|
243
|
-
*/
|
|
244
|
-
get actionSheet() {
|
|
245
|
-
return this.adaptiveRendererComponent?.actionSheet;
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* @hidden
|
|
249
|
-
*/
|
|
250
|
-
get actionSheetSearchBar() {
|
|
251
|
-
return this.adaptiveRendererComponent?.actionSheetSearchBar;
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* @hidden
|
|
255
|
-
*/
|
|
256
|
-
get isAdaptive() {
|
|
257
|
-
return this.isAdaptiveModeEnabled && this.windowSize !== 'large';
|
|
258
|
-
}
|
|
259
|
-
headerTemplate;
|
|
260
|
-
footerTemplate;
|
|
261
|
-
nodeTemplate;
|
|
262
|
-
noDataTemplate;
|
|
263
|
-
tagTemplate;
|
|
264
|
-
groupTagTemplate;
|
|
265
|
-
popupTemplate;
|
|
266
|
-
container;
|
|
267
|
-
set treeview(treeview) {
|
|
268
|
-
this._treeview = treeview;
|
|
269
|
-
if (treeview) {
|
|
270
|
-
// If filtering is enabled, focus the TreeView on mobile devices instead of the filter input
|
|
271
|
-
if (this.isFocused && !this.filterable && !this.checkAll || this.touchEnabled) {
|
|
272
|
-
treeview.focus();
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* the treeview animations are initially disabled (we don't want expand animations during popup opening)
|
|
276
|
-
* re-enables the animations for user interaction
|
|
277
|
-
* The Promise is required to properly change the `animate` property when
|
|
278
|
-
* the popup is appended to a container and opened upon initialization.
|
|
279
|
-
* Otherwise, the "Expression has changed..." type error will be thrown.
|
|
280
|
-
*/
|
|
281
|
-
Promise.resolve(null).then(() => this.treeview.animate = true);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
get treeview() {
|
|
285
|
-
return this._treeview;
|
|
286
|
-
}
|
|
287
|
-
filterInput;
|
|
288
|
-
checkAllInput;
|
|
289
|
-
/**
|
|
290
|
-
* Sets the tab index for keyboard navigation.
|
|
291
|
-
* Use `-1` to remove the component from the tab sequence.
|
|
292
|
-
*
|
|
293
|
-
* @default 0
|
|
294
|
-
*/
|
|
295
|
-
set tabindex(value) {
|
|
296
|
-
const providedTabIndex = parseNumber(value);
|
|
297
|
-
const defaultTabIndex = 0;
|
|
298
|
-
this._tabindex = !isNaN(providedTabIndex) ? providedTabIndex : defaultTabIndex;
|
|
299
|
-
}
|
|
300
|
-
get tabindex() {
|
|
301
|
-
return this.disabled ? -1 : this._tabindex;
|
|
302
|
-
}
|
|
303
|
-
/**
|
|
304
|
-
* Sets the visual size of the component.
|
|
305
|
-
*
|
|
306
|
-
* @default 'medium'
|
|
307
|
-
*/
|
|
308
|
-
set size(size) {
|
|
309
|
-
const newSize = size ? size : DEFAULT_SIZE;
|
|
310
|
-
this.renderer.removeClass(this.wrapper.nativeElement, getSizeClass('input', this.size));
|
|
311
|
-
if (size !== 'none') {
|
|
312
|
-
this.renderer.addClass(this.wrapper.nativeElement, getSizeClass('input', newSize));
|
|
313
|
-
}
|
|
314
|
-
this._size = newSize;
|
|
315
|
-
}
|
|
316
|
-
get size() {
|
|
317
|
-
return this._size;
|
|
318
|
-
}
|
|
319
|
-
/**
|
|
320
|
-
* Sets the border radius style of the component.
|
|
321
|
-
*
|
|
322
|
-
* @default 'medium'
|
|
323
|
-
*/
|
|
324
|
-
set rounded(rounded) {
|
|
325
|
-
const newRounded = rounded ? rounded : DEFAULT_ROUNDED;
|
|
326
|
-
this.renderer.removeClass(this.wrapper.nativeElement, getRoundedClass(this.rounded));
|
|
327
|
-
if (rounded !== 'none') {
|
|
328
|
-
this.renderer.addClass(this.wrapper.nativeElement, getRoundedClass(newRounded));
|
|
329
|
-
}
|
|
330
|
-
this._rounded = newRounded;
|
|
331
|
-
}
|
|
332
|
-
get rounded() {
|
|
333
|
-
return this._rounded;
|
|
334
|
-
}
|
|
335
|
-
/**
|
|
336
|
-
* Sets the fill style for the component background and borders.
|
|
337
|
-
*
|
|
338
|
-
* @default 'solid'
|
|
339
|
-
*/
|
|
340
|
-
set fillMode(fillMode) {
|
|
341
|
-
const newFillMode = fillMode ? fillMode : DEFAULT_FILL_MODE;
|
|
342
|
-
this.renderer.removeClass(this.wrapper.nativeElement, getFillModeClass('input', this.fillMode));
|
|
343
|
-
if (fillMode !== 'none') {
|
|
344
|
-
this.renderer.addClass(this.wrapper.nativeElement, getFillModeClass('input', newFillMode));
|
|
345
|
-
}
|
|
346
|
-
this._fillMode = newFillMode;
|
|
347
|
-
}
|
|
348
|
-
get fillMode() {
|
|
349
|
-
return this._fillMode;
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* Configures the popup container settings: animation, dimensions, styling and positioning.
|
|
353
|
-
*/
|
|
354
|
-
set popupSettings(settings) {
|
|
355
|
-
this._popupSettings = Object.assign({}, DEFAULT_POPUP_SETTINGS, settings);
|
|
356
|
-
// `detectChanges` needed, otherwise upon value initialization and `appendTo` property
|
|
357
|
-
// an error is thrown => ExpressionChangedAfterItHasBeenCheckedError
|
|
358
|
-
this.cdr.detectChanges();
|
|
359
|
-
}
|
|
360
|
-
get popupSettings() {
|
|
361
|
-
return this._popupSettings;
|
|
362
|
-
}
|
|
363
|
-
/**
|
|
364
|
-
* Configures the checkbox behavior for the MultiSelecTree nodes.
|
|
365
|
-
* Use `checkableSettings` to control parent-child selection relationships and click interactions.
|
|
366
|
-
*
|
|
367
|
-
* @default '{ checkChildren: true, checkOnClick: true }'
|
|
368
|
-
*/
|
|
369
|
-
set checkableSettings(settings) {
|
|
370
|
-
this._checkableSettings = Object.assign({}, DEFAULT_CHECKABLE_SETTINGS, settings);
|
|
371
|
-
}
|
|
372
|
-
get checkableSettings() {
|
|
373
|
-
return this._checkableSettings;
|
|
374
|
-
}
|
|
375
|
-
/**
|
|
376
|
-
* Sets the hierarchical data source for the tree structure.
|
|
377
|
-
* Provide an array of objects that contain the tree data and structure.
|
|
378
|
-
*/
|
|
379
|
-
set data(data) {
|
|
380
|
-
this._nodes = data;
|
|
381
|
-
this.setState();
|
|
382
|
-
if (this.isContentInit) {
|
|
383
|
-
// Needed for when the data is loaded later/asynchronously because it would not exist on ngContentInit
|
|
384
|
-
this.registerLookupItems(data);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
get data() {
|
|
388
|
-
return this._nodes;
|
|
389
|
-
}
|
|
390
|
-
/**
|
|
391
|
-
* Sets the selected values in the component.
|
|
392
|
-
* Accepts primitive values if `valuePrimitive` is `true`, or objects if `false`.
|
|
393
|
-
*/
|
|
394
|
-
set value(value) {
|
|
395
|
-
this._value = value ? value : [];
|
|
396
|
-
this.setState();
|
|
397
|
-
}
|
|
398
|
-
get value() {
|
|
399
|
-
return this._value;
|
|
400
|
-
}
|
|
401
|
-
/**
|
|
402
|
-
* Sets the data items that correspond to the selected values.
|
|
403
|
-
* Required when using primitive values to resolve the full data objects.
|
|
404
|
-
*/
|
|
405
|
-
set dataItems(items) {
|
|
406
|
-
this._dataItems = (items || []).map((dataItem, index) => {
|
|
407
|
-
if (hasProps(dataItem, ['dataItem', 'index', 'level'])) {
|
|
408
|
-
return dataItem;
|
|
409
|
-
}
|
|
410
|
-
const level = this.valueDepth[index] || 0;
|
|
411
|
-
const key = valueFrom({ dataItem, level }, this.valueField) + '_' + (this.isHeterogeneous ? this.valueDepth[index] : 0);
|
|
412
|
-
return {
|
|
413
|
-
dataItem,
|
|
414
|
-
index: null,
|
|
415
|
-
level,
|
|
416
|
-
key
|
|
417
|
-
};
|
|
418
|
-
});
|
|
419
|
-
this.setState();
|
|
420
|
-
}
|
|
421
|
-
get dataItems() {
|
|
422
|
-
return this._dataItems || this.value.map((value, index) => {
|
|
423
|
-
const level = this.valueDepth[index] || 0;
|
|
424
|
-
const key = valueFrom({ dataItem: value, level }, this.valueField) + '_' + (this.isHeterogeneous ? this.valueDepth[index] : 0);
|
|
425
|
-
return {
|
|
426
|
-
dataItem: value,
|
|
427
|
-
index: null,
|
|
428
|
-
level,
|
|
429
|
-
key
|
|
430
|
-
};
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
|
-
/**
|
|
434
|
-
* Specifies which data field provides the display text for tree nodes.
|
|
435
|
-
* > The `textField` property can be set to point to a nested property value - e.g. `category.name`.
|
|
436
|
-
*/
|
|
437
|
-
textField;
|
|
438
|
-
/**
|
|
439
|
-
* Specifies which data field provides the unique values for tree nodes.
|
|
440
|
-
* > The `valueField` property can be set to point to a nested property value - e.g. `category.id`.
|
|
441
|
-
*/
|
|
442
|
-
valueField;
|
|
443
|
-
/**
|
|
444
|
-
* Sets the levels in the data set where the values can be found when `valueField` is an Array.
|
|
445
|
-
* The field serves to correctly allocate a data item used when the MultiSelectTree is initialized with a value.
|
|
446
|
-
*
|
|
447
|
-
* @default []
|
|
448
|
-
*/
|
|
449
|
-
valueDepth = [];
|
|
450
|
-
/**
|
|
451
|
-
* Controls the loading state visual indicator.
|
|
452
|
-
* Shows a loading spinner when set to `true`.
|
|
453
|
-
*
|
|
454
|
-
* @default false
|
|
455
|
-
*/
|
|
456
|
-
loading;
|
|
457
|
-
/**
|
|
458
|
-
* Sets the placeholder text shown when no items are selected.
|
|
459
|
-
* Helps guide users on what action to take.
|
|
460
|
-
*
|
|
461
|
-
* @default ''
|
|
462
|
-
*/
|
|
463
|
-
placeholder = '';
|
|
464
|
-
/**
|
|
465
|
-
* Sets the maximum height of the options list in the popup.
|
|
466
|
-
* Controls vertical scrolling when content exceeds this height.
|
|
467
|
-
*
|
|
468
|
-
* @default 200
|
|
469
|
-
*/
|
|
470
|
-
set listHeight(_listHeight) {
|
|
471
|
-
this._listHeight = _listHeight;
|
|
472
|
-
}
|
|
473
|
-
get listHeight() {
|
|
474
|
-
if (this.isAdaptive) {
|
|
475
|
-
return;
|
|
476
|
-
}
|
|
477
|
-
return this._listHeight;
|
|
478
|
-
}
|
|
479
|
-
_listHeight = 200;
|
|
480
|
-
/**
|
|
481
|
-
* Controls whether the component accepts user input.
|
|
482
|
-
* Prevents all user interactions when set to `true`.
|
|
483
|
-
*
|
|
484
|
-
* @default false
|
|
485
|
-
*/
|
|
486
|
-
disabled = false;
|
|
487
|
-
/**
|
|
488
|
-
* Sets the component to read-only mode.
|
|
489
|
-
* Displays current selections but prevents changes.
|
|
490
|
-
*
|
|
491
|
-
* @default false
|
|
492
|
-
*/
|
|
493
|
-
readonly = false;
|
|
494
|
-
/**
|
|
495
|
-
* Determines the data type of selected values.
|
|
496
|
-
* Set to `true` for primitive values, false for complex objects.
|
|
497
|
-
*
|
|
498
|
-
* @default false
|
|
499
|
-
*/
|
|
500
|
-
valuePrimitive = false;
|
|
501
|
-
/**
|
|
502
|
-
* Controls when child nodes load from the data source.
|
|
503
|
-
* Set to `true` to load children only when parent nodes expand.
|
|
504
|
-
*
|
|
505
|
-
* @default false
|
|
506
|
-
*/
|
|
507
|
-
loadOnDemand = false;
|
|
508
|
-
/**
|
|
509
|
-
* Sets the unique identifier for the focusable element.
|
|
510
|
-
* Used internally for accessibility and label association.
|
|
511
|
-
*/
|
|
512
|
-
focusableId = `k-${guid()}`;
|
|
513
|
-
/**
|
|
514
|
-
* Shows a clear button to reset all selections.
|
|
515
|
-
* Appears on hover when selections exist and the component is not disabled.
|
|
516
|
-
*
|
|
517
|
-
* @default true
|
|
518
|
-
*/
|
|
519
|
-
clearButton = true;
|
|
520
|
-
/**
|
|
521
|
-
* Enables the built-in filter input for searching tree nodes.
|
|
522
|
-
* Shows a search box above the tree when enabled.
|
|
523
|
-
*
|
|
524
|
-
* @default false
|
|
525
|
-
*/
|
|
526
|
-
filterable = false;
|
|
527
|
-
/**
|
|
528
|
-
* Shows a checkbox to select or deselect all visible tree nodes.
|
|
529
|
-
* Appears above the tree when checkboxes are enabled.
|
|
530
|
-
*
|
|
531
|
-
* @default false
|
|
532
|
-
*/
|
|
533
|
-
checkAll = false;
|
|
534
|
-
/**
|
|
535
|
-
* Determines if a tree node contains child nodes.
|
|
536
|
-
* Return `true` if the node has children, false otherwise.
|
|
537
|
-
*/
|
|
538
|
-
hasChildren = hasChildren;
|
|
539
|
-
/**
|
|
540
|
-
* Function that provides child nodes for a parent node.
|
|
541
|
-
* Return an Observable of child objects for the given parent.
|
|
542
|
-
*/
|
|
543
|
-
fetchChildren = fetchChildren;
|
|
544
|
-
/**
|
|
545
|
-
* Determines if a specific node is expanded. The function is executed for each data item.
|
|
546
|
-
*/
|
|
547
|
-
isNodeExpanded;
|
|
548
|
-
/**
|
|
549
|
-
* Determines if a tree node should be hidden.
|
|
550
|
-
*/
|
|
551
|
-
isNodeVisible = isNodeVisible;
|
|
552
|
-
/**
|
|
553
|
-
* Determines if a tree node is disabled. The function is executed for each data item.
|
|
554
|
-
*/
|
|
555
|
-
itemDisabled = itemDisabled;
|
|
556
|
-
/**
|
|
557
|
-
* @param { Any[] } dataItems - The selected data items from the list.
|
|
558
|
-
* @returns { Any[] } - The tags that will be rendered by the component.
|
|
559
|
-
* Transforms the provided array of data items into an array of tags.
|
|
560
|
-
*/
|
|
561
|
-
tagMapper = (tags) => tags || [];
|
|
562
|
-
/**
|
|
563
|
-
* Fires when the component receives focus.
|
|
564
|
-
*/
|
|
565
|
-
onFocus = new EventEmitter();
|
|
566
|
-
/**
|
|
567
|
-
* Fires when the component gets blurred.
|
|
568
|
-
*/
|
|
569
|
-
onBlur = new EventEmitter();
|
|
570
|
-
/**
|
|
571
|
-
* Fires when the popup is about to open. ([See example]({% slug openstate_multiselecttree %})).
|
|
572
|
-
* This event is preventable. When cancelled, the popup remains closed.
|
|
573
|
-
*/
|
|
574
|
-
open = new EventEmitter();
|
|
575
|
-
/**
|
|
576
|
-
* Fires after the popup opens completely.
|
|
577
|
-
* Use this event to perform actions when the popup becomes visible.
|
|
578
|
-
*/
|
|
579
|
-
opened = new EventEmitter();
|
|
580
|
-
/**
|
|
581
|
-
* Fires before the popup closes.
|
|
582
|
-
* Cancel this event to prevent the popup from closing.
|
|
583
|
-
*/
|
|
584
|
-
close = new EventEmitter();
|
|
585
|
-
/**
|
|
586
|
-
* Fires after the popup closes completely.
|
|
587
|
-
* Use this event to perform cleanup actions when the popup becomes hidden.
|
|
588
|
-
*/
|
|
589
|
-
closed = new EventEmitter();
|
|
590
|
-
/**
|
|
591
|
-
* Fires when a tree node is expanded.
|
|
592
|
-
* Use this event to respond to node expansion actions.
|
|
593
|
-
*/
|
|
594
|
-
nodeExpand = new EventEmitter();
|
|
595
|
-
/**
|
|
596
|
-
* Fires when a user collapses a tree node.
|
|
597
|
-
* Use this event to respond to node collapse actions.
|
|
598
|
-
*/
|
|
599
|
-
nodeCollapse = new EventEmitter();
|
|
600
|
-
/**
|
|
601
|
-
* Fires when the selected value changes.
|
|
602
|
-
* Use this event to respond to selection changes.
|
|
603
|
-
*/
|
|
604
|
-
valueChange = new EventEmitter();
|
|
605
|
-
/**
|
|
606
|
-
* Fires before a tag is removed.
|
|
607
|
-
* Cancel this event to prevent tag removal.
|
|
608
|
-
*/
|
|
609
|
-
removeTag = new EventEmitter();
|
|
610
|
-
/**
|
|
611
|
-
* Fires when the filter input value changes.
|
|
612
|
-
* Use this event to implement custom filtering logic.
|
|
613
|
-
*/
|
|
614
|
-
filterChange = new EventEmitter();
|
|
615
|
-
/**
|
|
616
|
-
* @hidden
|
|
617
|
-
*/
|
|
618
|
-
get focusedTagId() {
|
|
619
|
-
if (!isPresent(this.focusedTagIndex) || this.isOpen) {
|
|
620
|
-
return null;
|
|
621
|
-
}
|
|
622
|
-
return this.tagPrefix + '-' + this.focusedTagIndex;
|
|
623
|
-
}
|
|
624
|
-
set isFocused(isFocused) {
|
|
625
|
-
this.renderer[isFocused ? 'addClass' : 'removeClass'](this.wrapper.nativeElement, 'k-focus');
|
|
626
|
-
this._isFocused = isFocused;
|
|
627
|
-
}
|
|
628
|
-
get isFocused() {
|
|
629
|
-
return this._isFocused;
|
|
630
|
-
}
|
|
631
|
-
/**
|
|
632
|
-
* Returns the current open state. Returns `true` if the popup or actionSheet is open.
|
|
633
|
-
*/
|
|
634
|
-
get isOpen() {
|
|
635
|
-
return isTruthy(isPresent(this.popupRef) || this.isActionSheetExpanded);
|
|
636
|
-
}
|
|
637
|
-
get width() {
|
|
638
|
-
const wrapperWidth = this.wrapper.nativeElement.offsetWidth;
|
|
639
|
-
const width = this.popupSettings.width || wrapperWidth;
|
|
640
|
-
const minWidth = isNaN(wrapperWidth) ? wrapperWidth : `${wrapperWidth}px`;
|
|
641
|
-
const maxWidth = isNaN(width) ? width : `${width}px`;
|
|
642
|
-
return { min: minWidth, max: maxWidth };
|
|
643
|
-
}
|
|
644
|
-
get height() {
|
|
645
|
-
const popupHeight = this.popupSettings.height;
|
|
646
|
-
return isPresent(popupHeight) ? `${popupHeight}px` : 'auto';
|
|
647
|
-
}
|
|
648
|
-
get appendTo() {
|
|
649
|
-
const { appendTo } = this.popupSettings;
|
|
650
|
-
if (!appendTo || appendTo === 'root') {
|
|
651
|
-
return undefined;
|
|
652
|
-
}
|
|
653
|
-
return appendTo === 'component' ? this.container : appendTo;
|
|
654
|
-
}
|
|
655
|
-
/**
|
|
656
|
-
* @hidden
|
|
657
|
-
*/
|
|
658
|
-
get popupContainerClasses() {
|
|
659
|
-
const containerClasses = ['k-multiselecttree-popup'];
|
|
660
|
-
if (!this.popupSettings.popupClass) {
|
|
661
|
-
return containerClasses;
|
|
662
|
-
}
|
|
663
|
-
const parsedPopupClasses = parseCSSClassNames(this.popupSettings.popupClass);
|
|
664
|
-
if (parsedPopupClasses?.length) {
|
|
665
|
-
containerClasses.push(...parsedPopupClasses);
|
|
666
|
-
}
|
|
667
|
-
return containerClasses;
|
|
668
|
-
}
|
|
669
|
-
/**
|
|
670
|
-
* @hidden
|
|
671
|
-
*
|
|
672
|
-
* Alias for `data`. Used for compatibility with the `DataBoundComponent` interface.
|
|
673
|
-
* Required for the data-binding directives.
|
|
674
|
-
*/
|
|
675
|
-
set nodes(nodes) {
|
|
676
|
-
this.data = nodes;
|
|
677
|
-
}
|
|
678
|
-
get nodes() {
|
|
679
|
-
return this.data;
|
|
680
|
-
}
|
|
681
|
-
/**
|
|
682
|
-
* @hidden
|
|
683
|
-
*
|
|
684
|
-
* Alias for `fetchChildren`. Used for compatibility with the `DataBoundComponent` interface.
|
|
685
|
-
* Required for the data-binding directives
|
|
686
|
-
*/
|
|
687
|
-
set children(callback) {
|
|
688
|
-
this.fetchChildren = callback;
|
|
689
|
-
}
|
|
690
|
-
get children() {
|
|
691
|
-
return this.fetchChildren;
|
|
692
|
-
}
|
|
693
|
-
/**
|
|
694
|
-
* @hidden
|
|
695
|
-
*
|
|
696
|
-
* Alias for `nodeExpand`. Used for compatibility with the `ExpandableComponent` interface.
|
|
697
|
-
* Required for the expand-directive.
|
|
698
|
-
*/
|
|
699
|
-
get expand() {
|
|
700
|
-
return this.nodeExpand;
|
|
701
|
-
}
|
|
702
|
-
/**
|
|
703
|
-
* @hidden
|
|
704
|
-
*
|
|
705
|
-
* Alias for `nodeCollapse`. Used for compatibility with the `ExpandableComponent` interface.
|
|
706
|
-
* Required for the expand-directive.
|
|
707
|
-
*/
|
|
708
|
-
get collapse() {
|
|
709
|
-
return this.nodeCollapse;
|
|
710
|
-
}
|
|
711
|
-
/**
|
|
712
|
-
* @hidden
|
|
713
|
-
*
|
|
714
|
-
* Alias for `isNodeExpanded`. Used for compatibility with the `ExpandableComponent` interface.
|
|
715
|
-
* Required for the expand-directive.
|
|
716
|
-
*/
|
|
717
|
-
set isExpanded(callback) {
|
|
718
|
-
this.isNodeExpanded = callback;
|
|
719
|
-
}
|
|
720
|
-
get isExpanded() {
|
|
721
|
-
return this.isNodeExpanded;
|
|
722
|
-
}
|
|
723
|
-
/**
|
|
724
|
-
* @hidden
|
|
725
|
-
*
|
|
726
|
-
* Alias for `isNodeVisible`. Used for compatibility with the `DataBoundComponent` interface.
|
|
727
|
-
* The `DataBoundComponent` interface is used in the data-binding directives.
|
|
728
|
-
*/
|
|
729
|
-
set isVisible(callback) {
|
|
730
|
-
this.isNodeVisible = callback;
|
|
731
|
-
}
|
|
732
|
-
get isVisible() {
|
|
733
|
-
return this.isNodeVisible;
|
|
734
|
-
}
|
|
735
|
-
get isTagFocused() {
|
|
736
|
-
return !this.isOpen && this.focusedTagIndex !== undefined;
|
|
737
|
-
}
|
|
738
|
-
get isTreeViewActive() {
|
|
739
|
-
return this.treeview && this.treeview.isActive;
|
|
740
|
-
}
|
|
741
|
-
get isWrapperActive() {
|
|
742
|
-
return document.activeElement === this.wrapper.nativeElement;
|
|
743
|
-
}
|
|
744
|
-
get isFilterActive() {
|
|
745
|
-
return this.filterInput && document.activeElement === this.filterInput.nativeElement;
|
|
746
|
-
}
|
|
747
|
-
get isCheckAllActive() {
|
|
748
|
-
return this.checkAllInput && document.activeElement === this.checkAllInput.nativeElement;
|
|
749
|
-
}
|
|
750
|
-
/**
|
|
751
|
-
* @hidden
|
|
752
|
-
*/
|
|
753
|
-
onResize() {
|
|
754
|
-
const currentWindowSize = this.adaptiveService.size;
|
|
755
|
-
if (this.isAdaptiveModeEnabled && this.windowSize !== currentWindowSize) {
|
|
756
|
-
if (this.isOpen) {
|
|
757
|
-
this.togglePopup(false);
|
|
758
|
-
}
|
|
759
|
-
this.windowSize = currentWindowSize;
|
|
760
|
-
}
|
|
761
|
-
if (this.isOpen && !this.isActionSheetExpanded) {
|
|
762
|
-
const popupWrapper = this.popupRef.popupElement;
|
|
763
|
-
const { min, max } = this.width;
|
|
764
|
-
popupWrapper.style.minWidth = min;
|
|
765
|
-
popupWrapper.style.width = max;
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
/**
|
|
769
|
-
* @hidden
|
|
770
|
-
*/
|
|
771
|
-
filterStateChange = new EventEmitter();
|
|
772
|
-
/**
|
|
773
|
-
* @hidden
|
|
774
|
-
*/
|
|
775
|
-
filter = '';
|
|
776
|
-
/**
|
|
777
|
-
* @hidden
|
|
778
|
-
*/
|
|
779
|
-
checkedItems = [];
|
|
780
|
-
/**
|
|
781
|
-
* @hidden
|
|
782
|
-
* The flag is needed in order to determine how to construct the items map keys.
|
|
783
|
-
* If `true`, then the key consists of the item's value and level (depth),
|
|
784
|
-
* else the key consists of the item's value and 0 (no leveling required)
|
|
785
|
-
*/
|
|
786
|
-
isHeterogeneous;
|
|
787
|
-
/**
|
|
788
|
-
* @hidden
|
|
789
|
-
*/
|
|
790
|
-
showAfter = 0;
|
|
791
|
-
/**
|
|
792
|
-
* @hidden
|
|
793
|
-
*/
|
|
794
|
-
allNodesHidden = false;
|
|
795
|
-
tagListId = `k-${guid()}`;
|
|
796
|
-
tagPrefix = "tag-" + guid();
|
|
797
|
-
popupRef;
|
|
798
|
-
tags;
|
|
799
|
-
focusedTagIndex = undefined;
|
|
800
|
-
disabledIndices;
|
|
801
|
-
_nodes;
|
|
802
|
-
_value = [];
|
|
803
|
-
_tabindex = 0;
|
|
804
|
-
_popupSettings = DEFAULT_POPUP_SETTINGS;
|
|
805
|
-
_checkableSettings = DEFAULT_CHECKABLE_SETTINGS;
|
|
806
|
-
_isFocused = false;
|
|
807
|
-
_treeview;
|
|
808
|
-
_dataItems;
|
|
809
|
-
_size = 'medium';
|
|
810
|
-
_rounded = 'medium';
|
|
811
|
-
_fillMode = 'solid';
|
|
812
|
-
_searchableNodes = [];
|
|
813
|
-
_typedValue = '';
|
|
814
|
-
printableCharacters = new Subject();
|
|
815
|
-
subs = new Subscription();
|
|
816
|
-
// Keep an instance of the last focused node for when the popup close is prevented
|
|
817
|
-
// in order to be able to properly restore the focus
|
|
818
|
-
lastNodeOnFocus;
|
|
819
|
-
// Used as check to avoid unnecessary 'registerLookupItems()' calls upon initialization
|
|
820
|
-
isContentInit;
|
|
821
|
-
constructor(injector, wrapper, popupService, renderer, navigationService, _zone, localization, cdr, lookup, adaptiveService) {
|
|
822
|
-
this.injector = injector;
|
|
823
|
-
this.wrapper = wrapper;
|
|
824
|
-
this.popupService = popupService;
|
|
825
|
-
this.renderer = renderer;
|
|
826
|
-
this.navigationService = navigationService;
|
|
827
|
-
this._zone = _zone;
|
|
828
|
-
this.localization = localization;
|
|
829
|
-
this.cdr = cdr;
|
|
830
|
-
this.lookup = lookup;
|
|
831
|
-
this.adaptiveService = adaptiveService;
|
|
832
|
-
this.direction = localization.rtl ? 'rtl' : 'ltr';
|
|
833
|
-
this.subscribeEvents();
|
|
834
|
-
this.subscribeFocusEvents();
|
|
835
|
-
}
|
|
836
|
-
ngOnInit() {
|
|
837
|
-
this.subs.add(this.printableCharacters.pipe(tap((char) => {
|
|
838
|
-
this._typedValue += char;
|
|
839
|
-
const itemToFocus = this._searchableNodes.find((node) => {
|
|
840
|
-
return node.text.toLowerCase().startsWith(this._typedValue);
|
|
841
|
-
});
|
|
842
|
-
this.treeview?.focus(itemToFocus?.index);
|
|
843
|
-
}), debounceTime(1000)).subscribe(() => {
|
|
844
|
-
this._typedValue = '';
|
|
845
|
-
}));
|
|
846
|
-
this.renderer.removeAttribute(this.wrapper.nativeElement, 'tabindex');
|
|
847
|
-
this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-expanded', String(this.isOpen));
|
|
848
|
-
this.subs.add(this.localization
|
|
849
|
-
.changes.subscribe(({ rtl }) => {
|
|
850
|
-
this.direction = rtl ? 'rtl' : 'ltr';
|
|
851
|
-
this.cdr.markForCheck();
|
|
852
|
-
}));
|
|
853
|
-
this.setComponentClasses();
|
|
854
|
-
}
|
|
855
|
-
ngAfterViewInit() {
|
|
856
|
-
this.windowSize = this.adaptiveService.size;
|
|
857
|
-
this.subs.add(this.renderer.listen(this.wrapper.nativeElement, 'click', this.handleClick.bind(this)));
|
|
858
|
-
this.subs.add(this.renderer.listen(this.wrapper.nativeElement, 'keydown', this.handleKeydown.bind(this)));
|
|
859
|
-
}
|
|
860
|
-
/**
|
|
861
|
-
* @hidden
|
|
862
|
-
*/
|
|
863
|
-
ngOnDestroy() {
|
|
864
|
-
this.destroyPopup();
|
|
865
|
-
this.unsubscribeEvents();
|
|
866
|
-
}
|
|
867
|
-
/**
|
|
868
|
-
* @hidden
|
|
869
|
-
*/
|
|
870
|
-
ngOnChanges(changes) {
|
|
871
|
-
if (anyChanged(['textField', 'valueField', 'valuePrimitive'], changes, false)) {
|
|
872
|
-
this.isHeterogeneous = this.valueField && isArray(this.valueField);
|
|
873
|
-
this.setState();
|
|
874
|
-
}
|
|
875
|
-
if (anyChanged(['valueDepth', 'value', 'dataItems'], changes, false)) {
|
|
876
|
-
if (changes['value'] && !changes['dataItems'] && !this.valuePrimitive) {
|
|
877
|
-
// Update the dataItems if the value is updated programmatically (non-primitive values only)
|
|
878
|
-
// In the primitive case, the client should update the dataItems as well
|
|
879
|
-
this.dataItems = this.value;
|
|
880
|
-
}
|
|
881
|
-
else {
|
|
882
|
-
// Re-map the dataItems because `valueDepth` is not yet available when the check directive parses the items
|
|
883
|
-
this.dataItems = this.dataItems.map((item, index) => ({
|
|
884
|
-
...item,
|
|
885
|
-
key: valueFrom({ dataItem: item.dataItem, index: null, level: this.valueDepth[index] || 0 }, this.valueField) + '_' + (this.isHeterogeneous ? this.valueDepth[index] : 0),
|
|
886
|
-
level: this.valueDepth[index] || 0
|
|
887
|
-
}));
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
if (anyChanged(['data', 'children', 'hasChildren', 'loadOnDemand', 'valueField'], changes, true) && !this.loadOnDemand) {
|
|
891
|
-
this.lookup.reset();
|
|
892
|
-
this.registerLookupItems(this.data);
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
/**
|
|
896
|
-
* @hidden
|
|
897
|
-
*/
|
|
898
|
-
ngAfterContentChecked() {
|
|
899
|
-
this.verifySettings();
|
|
900
|
-
if (this.data?.length > 0 && this.popupRef) {
|
|
901
|
-
this.allNodesHidden = this.areNodesHidden(this.data);
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
ngAfterContentInit() {
|
|
905
|
-
this.isContentInit = true;
|
|
906
|
-
// Still need to keep the call of 'registerLookupItems()' from ngAfterContentInit in the cases when the data is passed initially
|
|
907
|
-
// The call is execute here because we have to make sure it happens after all input properties are loaded (not the case in the data setter initially)
|
|
908
|
-
this.registerLookupItems(this.data);
|
|
909
|
-
}
|
|
910
|
-
/**
|
|
911
|
-
* @hidden
|
|
912
|
-
*
|
|
913
|
-
* Used by the kendo-floatinglabel component to determine if the floating label
|
|
914
|
-
* should be rendered inside the input when the component is not focused.
|
|
915
|
-
*/
|
|
916
|
-
isEmpty() {
|
|
917
|
-
return !this.placeholder && (!isPresent(this.value) || this.value.length === 0);
|
|
918
|
-
}
|
|
919
|
-
/**
|
|
920
|
-
* Sets focus to the component.
|
|
921
|
-
* Call this method to programmatically focus the MultiSelectTree.
|
|
922
|
-
*/
|
|
923
|
-
focus() {
|
|
924
|
-
if (!this.disabled) {
|
|
925
|
-
this.wrapper.nativeElement.focus();
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
/**
|
|
929
|
-
* Removes focus from the component.
|
|
930
|
-
* Call this method to programmatically blur the MultiSelectTree.
|
|
931
|
-
*/
|
|
932
|
-
blur() {
|
|
933
|
-
if (!this.disabled) {
|
|
934
|
-
this.wrapper.nativeElement.blur();
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
/**
|
|
938
|
-
* Sets focus to a specific tree item by index.
|
|
939
|
-
* Provide the item index in format like '1_1' to focus that item.
|
|
940
|
-
* The item must be expanded and enabled to receive focus.
|
|
941
|
-
*/
|
|
942
|
-
focusItemAt(index) {
|
|
943
|
-
if (this.treeview) {
|
|
944
|
-
const lookup = this.treeview.itemLookup(index);
|
|
945
|
-
const isItemDisabled = !isPresent(lookup) || this.treeview.isDisabled(lookup.item.dataItem, lookup.item.index);
|
|
946
|
-
if (!isItemDisabled) {
|
|
947
|
-
this.treeview.focus(index);
|
|
948
|
-
}
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
/**
|
|
952
|
-
* Clears all selected values from the component.
|
|
953
|
-
* This method does not trigger the valueChange event.
|
|
954
|
-
*/
|
|
955
|
-
reset() {
|
|
956
|
-
this.value = [];
|
|
957
|
-
this.dataItems = [];
|
|
958
|
-
this.valueDepth = [];
|
|
959
|
-
}
|
|
960
|
-
/**
|
|
961
|
-
* Opens or closes the popup programmatically.
|
|
962
|
-
* Pass `true` to open, false to close, or omit the parameter to toggle.
|
|
963
|
-
* This method does not trigger open or close events.
|
|
964
|
-
*/
|
|
965
|
-
toggle(open) {
|
|
966
|
-
// The Promise is required to open the popup on load.
|
|
967
|
-
// Otherwise, the "ViewContainerRef not found..." error will be thrown.
|
|
968
|
-
Promise.resolve(null).then(() => {
|
|
969
|
-
const shouldOpen = isPresent(open) ? open : !isPresent(this.popupRef);
|
|
970
|
-
this.destroyPopup();
|
|
971
|
-
if (shouldOpen) {
|
|
972
|
-
this.createPopup();
|
|
973
|
-
}
|
|
974
|
-
});
|
|
975
|
-
}
|
|
976
|
-
/**
|
|
977
|
-
* @hidden
|
|
978
|
-
*/
|
|
979
|
-
handleFocus(event) {
|
|
980
|
-
if (event.target !== this.wrapper.nativeElement) {
|
|
981
|
-
return;
|
|
982
|
-
}
|
|
983
|
-
event.stopImmediatePropagation();
|
|
984
|
-
if (!this.isFocused) {
|
|
985
|
-
this.isFocused = true;
|
|
986
|
-
if (hasObservers(this.onFocus)) {
|
|
987
|
-
this._zone.run(() => {
|
|
988
|
-
this.onFocus.emit();
|
|
989
|
-
});
|
|
990
|
-
}
|
|
991
|
-
// Re-focus the treeview if `close` is prevented
|
|
992
|
-
if (this.isOpen && this.treeview) {
|
|
993
|
-
if (this.lastNodeOnFocus) {
|
|
994
|
-
this.lastNodeOnFocus.setAttribute('tabindex', '0');
|
|
995
|
-
}
|
|
996
|
-
this.treeview.focus();
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
/**
|
|
1001
|
-
* @hidden
|
|
1002
|
-
*/
|
|
1003
|
-
handleBlur(e) {
|
|
1004
|
-
if (!this.isActionSheetExpanded) {
|
|
1005
|
-
const relatedTarget = e && e.relatedTarget;
|
|
1006
|
-
if (this.wrapper.nativeElement.contains(relatedTarget) ||
|
|
1007
|
-
(this.isOpen && this.popupRef.popupElement.contains(relatedTarget))) {
|
|
1008
|
-
return;
|
|
1009
|
-
}
|
|
1010
|
-
this.isFocused = false;
|
|
1011
|
-
this.togglePopup(false);
|
|
1012
|
-
//this is needed for Ang 18 not to throw ng0100 error when closing the popup
|
|
1013
|
-
//the component could be refactored using kendoDropDownSharedEvents directive
|
|
1014
|
-
//once we are able to debug against Angular 18
|
|
1015
|
-
this.cdr.markForCheck();
|
|
1016
|
-
if (hasObservers(this.onBlur) ||
|
|
1017
|
-
isUntouched(this.wrapper.nativeElement) ||
|
|
1018
|
-
this.formControl?.updateOn === 'blur') {
|
|
1019
|
-
this._zone.run(() => {
|
|
1020
|
-
this.onBlur.emit();
|
|
1021
|
-
this.onTouchedCallback();
|
|
1022
|
-
});
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
/**
|
|
1027
|
-
* @hidden
|
|
1028
|
-
*/
|
|
1029
|
-
handleNodeClick(node) {
|
|
1030
|
-
if (!this.isFocused) {
|
|
1031
|
-
// Re-focus the MultiSelectTree when popup close is prevented and a node is clicked
|
|
1032
|
-
// On click the focus should be on the clicked element which is why we need to update the lastNodeOnFocus
|
|
1033
|
-
const parent = node.originalEvent.target.parentElement.parentElement;
|
|
1034
|
-
this.lastNodeOnFocus = parent;
|
|
1035
|
-
this.focus();
|
|
1036
|
-
}
|
|
1037
|
-
}
|
|
1038
|
-
/**
|
|
1039
|
-
* @hidden
|
|
1040
|
-
*/
|
|
1041
|
-
togglePopup(open) {
|
|
1042
|
-
const isDisabled = this.disabled || this.readonly;
|
|
1043
|
-
const sameState = this.isOpen === open;
|
|
1044
|
-
this._zone.run(() => {
|
|
1045
|
-
this.focusedTagIndex = undefined;
|
|
1046
|
-
});
|
|
1047
|
-
if (isDisabled || sameState) {
|
|
1048
|
-
return;
|
|
1049
|
-
}
|
|
1050
|
-
const togglePrevented = this.triggerPopupEvents(open);
|
|
1051
|
-
if (!togglePrevented) {
|
|
1052
|
-
if (open) {
|
|
1053
|
-
this.createPopup();
|
|
1054
|
-
}
|
|
1055
|
-
else {
|
|
1056
|
-
this.destroyPopup();
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
else {
|
|
1060
|
-
this.removeTreeViewFromTabOrder();
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
/**
|
|
1064
|
-
* @hidden
|
|
1065
|
-
*/
|
|
1066
|
-
messageFor(key) {
|
|
1067
|
-
return this.localization.get(key);
|
|
1068
|
-
}
|
|
1069
|
-
lastAction = 'check';
|
|
1070
|
-
/**
|
|
1071
|
-
* @hidden
|
|
1072
|
-
*/
|
|
1073
|
-
handleCheckedItemsChange(items) {
|
|
1074
|
-
this.valueDepth = items.map(item => item.level);
|
|
1075
|
-
this.lastAction = items.length > this.dataItems.length ? 'check' : 'uncheck';
|
|
1076
|
-
this.dataItems = items.slice();
|
|
1077
|
-
this.updateValue(this.dataItems);
|
|
1078
|
-
}
|
|
1079
|
-
/**
|
|
1080
|
-
* @hidden
|
|
1081
|
-
*/
|
|
1082
|
-
handleRemoveTag({ tag, index }) {
|
|
1083
|
-
if (this.disabled || this.readonly) {
|
|
1084
|
-
return;
|
|
1085
|
-
}
|
|
1086
|
-
const eventArgs = new RemoveTagEvent(tag);
|
|
1087
|
-
this.removeTag.emit(eventArgs);
|
|
1088
|
-
if (eventArgs.isDefaultPrevented()) {
|
|
1089
|
-
return;
|
|
1090
|
-
}
|
|
1091
|
-
// Remove tags based on their position index
|
|
1092
|
-
if (tag instanceof Array) {
|
|
1093
|
-
// Remove group tag
|
|
1094
|
-
this.dataItems = this.dataItems.filter((_item, i) => i < this.showAfter || this.disabledIndices.has(i));
|
|
1095
|
-
this.valueDepth = this.valueDepth.filter((_item, i) => i < this.showAfter || this.disabledIndices.has(i));
|
|
1096
|
-
}
|
|
1097
|
-
else if (this.loadOnDemand) {
|
|
1098
|
-
// Remove single tag when the child items are fetched on demand
|
|
1099
|
-
this.dataItems = this.dataItems.filter((_item, i) => i !== index || this.disabledIndices.has(i));
|
|
1100
|
-
this.valueDepth = this.valueDepth.filter((_item, i) => i !== index || this.disabledIndices.has(i));
|
|
1101
|
-
}
|
|
1102
|
-
else {
|
|
1103
|
-
// Remove single tag when the child items are pre-fetched
|
|
1104
|
-
const dataItem = this.dataItems.find(item => item.tagPositionIndex === index);
|
|
1105
|
-
const itemKey = dataItem.key;
|
|
1106
|
-
const lookup = this.lookup.itemLookup(itemKey);
|
|
1107
|
-
const pendingCheck = [lookup.item];
|
|
1108
|
-
if (this.checkableSettings.checkChildren) {
|
|
1109
|
-
fetchDescendentNodes(lookup)
|
|
1110
|
-
.forEach(lookup => pendingCheck.push(lookup.item));
|
|
1111
|
-
pendingCheck.push(...this.removeParents(lookup.parent));
|
|
1112
|
-
}
|
|
1113
|
-
const keysToRemove = pendingCheck.map(item => item.key);
|
|
1114
|
-
// Holds the position indexes of the items to be removed
|
|
1115
|
-
const valueDepthIndices = [];
|
|
1116
|
-
this.dataItems = this.dataItems.filter((_item, i) => {
|
|
1117
|
-
const shouldStay = !keysToRemove.includes(_item.key) || this.disabledIndices.has(i);
|
|
1118
|
-
if (!shouldStay) {
|
|
1119
|
-
// We need to know the index position of the data item to be able to update the valueDepth array accordignly
|
|
1120
|
-
// as each data item's position is corresponding to the same position in valueDepth
|
|
1121
|
-
valueDepthIndices.push(i);
|
|
1122
|
-
}
|
|
1123
|
-
return shouldStay;
|
|
1124
|
-
});
|
|
1125
|
-
this.valueDepth = this.valueDepth.filter((_item, i) => {
|
|
1126
|
-
return !valueDepthIndices.includes(i) || this.disabledIndices.has(i);
|
|
1127
|
-
});
|
|
1128
|
-
}
|
|
1129
|
-
this.updateValue(this.dataItems);
|
|
1130
|
-
if (!this.isFocused) {
|
|
1131
|
-
this.focus();
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
/**
|
|
1135
|
-
* @hidden
|
|
1136
|
-
*/
|
|
1137
|
-
handleTagMapperChange(showAfter) {
|
|
1138
|
-
this.showAfter = parseNumber(showAfter);
|
|
1139
|
-
this.setTags();
|
|
1140
|
-
}
|
|
1141
|
-
/**
|
|
1142
|
-
* @hidden
|
|
1143
|
-
*/
|
|
1144
|
-
clearAll(event) {
|
|
1145
|
-
event?.stopImmediatePropagation();
|
|
1146
|
-
event?.preventDefault();
|
|
1147
|
-
this.focus();
|
|
1148
|
-
this.value = this.value.filter((_item, index) => this.disabledIndices.has(index));
|
|
1149
|
-
this.dataItems = this.dataItems.filter((_item, index) => this.disabledIndices.has(index));
|
|
1150
|
-
this.valueDepth = this.valueDepth.filter((_depth, index) => this.disabledIndices.has(index));
|
|
1151
|
-
this.emitValueChange(this.value);
|
|
1152
|
-
}
|
|
1153
|
-
/**
|
|
1154
|
-
* @hidden
|
|
1155
|
-
*/
|
|
1156
|
-
writeValue(value) {
|
|
1157
|
-
if (!this.valuePrimitive && isPresent(value)) {
|
|
1158
|
-
this.dataItems = value;
|
|
1159
|
-
}
|
|
1160
|
-
if (!isPresent(value) && isPresent(this.value)) {
|
|
1161
|
-
this.dataItems = null;
|
|
1162
|
-
}
|
|
1163
|
-
this.value = value || [];
|
|
1164
|
-
}
|
|
1165
|
-
/**
|
|
1166
|
-
* @hidden
|
|
1167
|
-
*/
|
|
1168
|
-
registerOnChange(fn) {
|
|
1169
|
-
this.onChangeCallback = fn;
|
|
1170
|
-
}
|
|
1171
|
-
/**
|
|
1172
|
-
* @hidden
|
|
1173
|
-
*/
|
|
1174
|
-
registerOnTouched(fn) {
|
|
1175
|
-
this.onTouchedCallback = fn;
|
|
1176
|
-
}
|
|
1177
|
-
/**
|
|
1178
|
-
* @hidden
|
|
1179
|
-
*/
|
|
1180
|
-
setDisabledState(isDisabled) {
|
|
1181
|
-
this.disabled = isDisabled;
|
|
1182
|
-
this.cdr.markForCheck();
|
|
1183
|
-
}
|
|
1184
|
-
/**
|
|
1185
|
-
* @hidden
|
|
1186
|
-
*/
|
|
1187
|
-
handleFilterInputChange(input) {
|
|
1188
|
-
this.filter = input.value;
|
|
1189
|
-
this.filterChange.next(input.value);
|
|
1190
|
-
}
|
|
1191
|
-
/**
|
|
1192
|
-
* @hidden
|
|
1193
|
-
*/
|
|
1194
|
-
get filterInputClasses() {
|
|
1195
|
-
return `${this.size ? getSizeClass('input', this.size) : ''} ${this.fillMode ? 'k-input-' + this.fillMode : ''} ${this.rounded ? getRoundedClass(this.rounded) : ''}`;
|
|
1196
|
-
}
|
|
1197
|
-
/**
|
|
1198
|
-
* @hidden
|
|
1199
|
-
*/
|
|
1200
|
-
get checkAllCheckboxClasses() {
|
|
1201
|
-
return `${this.size ? getSizeClass('checkbox', this.size) : ''}`;
|
|
1202
|
-
}
|
|
1203
|
-
/**
|
|
1204
|
-
* @hidden
|
|
1205
|
-
*/
|
|
1206
|
-
toggleCheckAll() {
|
|
1207
|
-
this.checkAllInput.nativeElement.focus();
|
|
1208
|
-
this.checkAllInput.nativeElement.click();
|
|
1209
|
-
}
|
|
1210
|
-
onTouchedCallback = noop;
|
|
1211
|
-
onChangeCallback = noop;
|
|
1212
|
-
verifySettings() {
|
|
1213
|
-
if (!isDevMode()) {
|
|
1214
|
-
return;
|
|
1215
|
-
}
|
|
1216
|
-
if (!isPresent(this.valueField) || !isPresent(this.textField)) {
|
|
1217
|
-
throw new Error(MultiSelectTreeMessages.textAndValue);
|
|
1218
|
-
}
|
|
1219
|
-
if (!isArray(this.value)) {
|
|
1220
|
-
throw new Error(MultiSelectTreeMessages.array);
|
|
1221
|
-
}
|
|
1222
|
-
if (this.value.length > 0) {
|
|
1223
|
-
if (this.valuePrimitive && this.value.some(item => isObject(item))) {
|
|
1224
|
-
throw new Error(MultiSelectTreeMessages.primitive);
|
|
1225
|
-
}
|
|
1226
|
-
const isEveryDataItemObject = this.dataItems.every(item => isObject(item.dataItem));
|
|
1227
|
-
if (this.valuePrimitive && !isArray(this.dataItems)) {
|
|
1228
|
-
throw new Error(MultiSelectTreeMessages.dataItems);
|
|
1229
|
-
}
|
|
1230
|
-
if (this.valuePrimitive && !isEveryDataItemObject) {
|
|
1231
|
-
throw new Error(MultiSelectTreeMessages.dataItems);
|
|
1232
|
-
}
|
|
1233
|
-
if (this.valuePrimitive && this.dataItems.length !== this.value.length) {
|
|
1234
|
-
throw new Error(MultiSelectTreeMessages.dataItemsLength);
|
|
1235
|
-
}
|
|
1236
|
-
if (!this.valuePrimitive && !isObjectArray(this.value)) {
|
|
1237
|
-
throw new Error(MultiSelectTreeMessages.object);
|
|
1238
|
-
}
|
|
1239
|
-
if ((isArray(this.valueField) || isArray(this.textField)) && !isArray(this.valueDepth)) {
|
|
1240
|
-
throw new Error(MultiSelectTreeMessages.valueDepth);
|
|
1241
|
-
}
|
|
1242
|
-
if ((isArray(this.valueField) || isArray(this.textField)) && this.valueDepth.length === 0) {
|
|
1243
|
-
throw new Error(MultiSelectTreeMessages.valueDepth);
|
|
1244
|
-
}
|
|
1245
|
-
if ((isArray(this.valueField) || isArray(this.textField)) && this.valueDepth.length !== this.value.length) {
|
|
1246
|
-
throw new Error(MultiSelectTreeMessages.valueDepthLength);
|
|
1247
|
-
}
|
|
1248
|
-
}
|
|
1249
|
-
}
|
|
1250
|
-
areNodesHidden(nodes) {
|
|
1251
|
-
return nodes.every((node, index) => !this.isVisible(node, String(index)));
|
|
1252
|
-
}
|
|
1253
|
-
emitValueChange(value) {
|
|
1254
|
-
this.onChangeCallback(value);
|
|
1255
|
-
this.valueChange.emit(value);
|
|
1256
|
-
}
|
|
1257
|
-
triggerPopupEvents(open) {
|
|
1258
|
-
const eventArgs = new PreventableEvent();
|
|
1259
|
-
if (hasObservers(this.open) || hasObservers(this.close)) {
|
|
1260
|
-
this._zone.run(() => {
|
|
1261
|
-
if (open) {
|
|
1262
|
-
this.open.emit(eventArgs);
|
|
1263
|
-
}
|
|
1264
|
-
else {
|
|
1265
|
-
this.close.emit(eventArgs);
|
|
1266
|
-
}
|
|
1267
|
-
});
|
|
1268
|
-
}
|
|
1269
|
-
return eventArgs.isDefaultPrevented();
|
|
1270
|
-
}
|
|
1271
|
-
createPopup() {
|
|
1272
|
-
this.windowSize = this.adaptiveService.size;
|
|
1273
|
-
if (this.isAdaptive) {
|
|
1274
|
-
this.openActionSheet();
|
|
1275
|
-
this.cdr.detectChanges();
|
|
1276
|
-
return;
|
|
1277
|
-
}
|
|
1278
|
-
const horizontalAlign = this.direction === "rtl" ? "right" : "left";
|
|
1279
|
-
const anchorPosition = { horizontal: horizontalAlign, vertical: 'bottom' };
|
|
1280
|
-
const popupPosition = { horizontal: horizontalAlign, vertical: 'top' };
|
|
1281
|
-
const appendToComponent = typeof this.popupSettings.appendTo === 'string' && this.popupSettings.appendTo === 'component';
|
|
1282
|
-
this.popupRef = this.popupService.open({
|
|
1283
|
-
anchor: this.wrapper,
|
|
1284
|
-
appendTo: this.appendTo,
|
|
1285
|
-
anchorAlign: anchorPosition,
|
|
1286
|
-
animate: this.popupSettings.animate,
|
|
1287
|
-
content: this.popupTemplate,
|
|
1288
|
-
popupAlign: popupPosition,
|
|
1289
|
-
positionMode: appendToComponent ? 'fixed' : 'absolute',
|
|
1290
|
-
popupClass: this.popupContainerClasses
|
|
1291
|
-
});
|
|
1292
|
-
const popupWrapper = this.popupRef.popupElement;
|
|
1293
|
-
const { min, max } = this.width;
|
|
1294
|
-
if (!this.appendTo) {
|
|
1295
|
-
this.renderer.setAttribute(popupWrapper, 'role', 'region');
|
|
1296
|
-
this.renderer.setAttribute(popupWrapper, 'aria-label', this.messageFor('popupLabel'));
|
|
1297
|
-
}
|
|
1298
|
-
popupWrapper.style.minWidth = min;
|
|
1299
|
-
popupWrapper.style.width = max;
|
|
1300
|
-
popupWrapper.style.height = this.height;
|
|
1301
|
-
this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-controls', this.treeViewId);
|
|
1302
|
-
this.renderer.setAttribute(popupWrapper, 'dir', this.direction);
|
|
1303
|
-
this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-expanded', 'true');
|
|
1304
|
-
this.popupRef.popupOpen.subscribe(() => {
|
|
1305
|
-
this.cdr.detectChanges();
|
|
1306
|
-
this.opened.emit();
|
|
1307
|
-
this._searchableNodes = getSearchableItems(this.treeViewId, this.popupRef.popupElement);
|
|
1308
|
-
});
|
|
1309
|
-
this.popupRef.popupClose.subscribe(() => {
|
|
1310
|
-
if (hasObservers(this.closed)) {
|
|
1311
|
-
this._zone.run(() => {
|
|
1312
|
-
this.closed.emit();
|
|
1313
|
-
});
|
|
1314
|
-
}
|
|
1315
|
-
});
|
|
1316
|
-
}
|
|
1317
|
-
destroyPopup() {
|
|
1318
|
-
if (this.isActionSheetExpanded) {
|
|
1319
|
-
this.closeActionSheet();
|
|
1320
|
-
}
|
|
1321
|
-
if (this.popupRef) {
|
|
1322
|
-
this.popupRef.close();
|
|
1323
|
-
this.popupRef = null;
|
|
1324
|
-
this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-expanded', 'false');
|
|
1325
|
-
this.renderer.removeAttribute(this.wrapper.nativeElement, 'aria-controls');
|
|
1326
|
-
this.clearFilter();
|
|
1327
|
-
}
|
|
1328
|
-
}
|
|
1329
|
-
clearFilter() {
|
|
1330
|
-
if (this.filter !== "") {
|
|
1331
|
-
this.filter = "";
|
|
1332
|
-
this.allNodesHidden = false;
|
|
1333
|
-
if (hasObservers(this.filterChange)) {
|
|
1334
|
-
this._zone.run(() => {
|
|
1335
|
-
this.filterChange.emit("");
|
|
1336
|
-
});
|
|
1337
|
-
}
|
|
1338
|
-
}
|
|
1339
|
-
}
|
|
1340
|
-
handleClick(e) {
|
|
1341
|
-
// The check is needed otherwise when appended to the component, the popup reopens on click
|
|
1342
|
-
// https://github.com/telerik/kendo-angular/issues/3738
|
|
1343
|
-
if ((this.popupRef && this.popupRef.popupElement.contains(e.target)) || this.isActionSheetExpanded) {
|
|
1344
|
-
return;
|
|
1345
|
-
}
|
|
1346
|
-
this.togglePopup(!this.isOpen);
|
|
1347
|
-
}
|
|
1348
|
-
subscribeEvents() {
|
|
1349
|
-
[
|
|
1350
|
-
this.navigationService.open.subscribe((event) => {
|
|
1351
|
-
event.originalEvent.preventDefault();
|
|
1352
|
-
this.togglePopup(true);
|
|
1353
|
-
}),
|
|
1354
|
-
this.navigationService.enter
|
|
1355
|
-
.pipe(tap((event) => event.originalEvent.preventDefault()))
|
|
1356
|
-
.subscribe(() => this.togglePopup(true)),
|
|
1357
|
-
merge(this.navigationService.close).subscribe((event) => {
|
|
1358
|
-
event.originalEvent.preventDefault();
|
|
1359
|
-
this.focus();
|
|
1360
|
-
this.togglePopup(false);
|
|
1361
|
-
}),
|
|
1362
|
-
this.navigationService.tab.subscribe(this.handleTabKey.bind(this)),
|
|
1363
|
-
this.navigationService.up.subscribe(this.handleUpKey.bind(this)),
|
|
1364
|
-
this.navigationService.down.subscribe(this.handleDownKey.bind(this)),
|
|
1365
|
-
this.navigationService.esc.subscribe(() => {
|
|
1366
|
-
if (this.isOpen) {
|
|
1367
|
-
this.togglePopup(false);
|
|
1368
|
-
this.focus();
|
|
1369
|
-
}
|
|
1370
|
-
else if (this.isFocused && this.checkedItems.length > 0) {
|
|
1371
|
-
this.clearAll();
|
|
1372
|
-
}
|
|
1373
|
-
}),
|
|
1374
|
-
this.navigationService.left
|
|
1375
|
-
.pipe(filter(() => !this.isTreeViewActive))
|
|
1376
|
-
.subscribe(this.direction === 'rtl' ? this.handleRightKey.bind(this) : this.handleLeftKey.bind(this)),
|
|
1377
|
-
this.navigationService.right
|
|
1378
|
-
.pipe(filter(() => !this.isTreeViewActive))
|
|
1379
|
-
.subscribe(this.direction === 'rtl' ? this.handleLeftKey.bind(this) : this.handleRightKey.bind(this)),
|
|
1380
|
-
this.navigationService.home.pipe(filter(() => !this.isOpen)).subscribe(this.handleHome.bind(this)),
|
|
1381
|
-
this.navigationService.end.pipe(filter(() => !this.isOpen)).subscribe(this.handleEnd.bind(this)),
|
|
1382
|
-
this.navigationService.backspace.pipe(filter(() => this.isTagFocused)).subscribe(this.handleBackspace.bind(this)),
|
|
1383
|
-
this.navigationService.delete.pipe(filter(() => this.isTagFocused)).subscribe(this.handleDelete.bind(this))
|
|
1384
|
-
].forEach(sub => this.subs.add(sub));
|
|
1385
|
-
}
|
|
1386
|
-
subscribeFocusEvents() {
|
|
1387
|
-
if (isDocumentAvailable()) {
|
|
1388
|
-
this.handleFocus = this.handleFocus.bind(this);
|
|
1389
|
-
this.handleDocumentBlur = this.handleDocumentBlur.bind(this);
|
|
1390
|
-
this._zone.runOutsideAngular(() => {
|
|
1391
|
-
const useCapture = true;
|
|
1392
|
-
document.addEventListener('focus', this.handleFocus, useCapture);
|
|
1393
|
-
document.addEventListener('blur', this.handleDocumentBlur, useCapture);
|
|
1394
|
-
});
|
|
1395
|
-
}
|
|
1396
|
-
}
|
|
1397
|
-
unSubscribeFocusEvents() {
|
|
1398
|
-
if (isDocumentAvailable()) {
|
|
1399
|
-
const useCapture = true;
|
|
1400
|
-
document.removeEventListener('focus', this.handleFocus, useCapture);
|
|
1401
|
-
document.removeEventListener('blur', this.handleDocumentBlur, useCapture);
|
|
1402
|
-
}
|
|
1403
|
-
}
|
|
1404
|
-
handleDocumentBlur(event) {
|
|
1405
|
-
if (event.target !== this.wrapper.nativeElement) {
|
|
1406
|
-
return;
|
|
1407
|
-
}
|
|
1408
|
-
event.stopImmediatePropagation();
|
|
1409
|
-
this.handleBlur(event);
|
|
1410
|
-
}
|
|
1411
|
-
handleTabKey() {
|
|
1412
|
-
if (!this.isActionSheetExpanded) {
|
|
1413
|
-
this.focus();
|
|
1414
|
-
}
|
|
1415
|
-
if (this.isOpen) {
|
|
1416
|
-
this.treeview.blur();
|
|
1417
|
-
this.removeTreeViewFromTabOrder();
|
|
1418
|
-
}
|
|
1419
|
-
}
|
|
1420
|
-
handleUpKey(event) {
|
|
1421
|
-
if (!this.treeview) {
|
|
1422
|
-
return;
|
|
1423
|
-
}
|
|
1424
|
-
event.originalEvent.preventDefault();
|
|
1425
|
-
// Prevent toggling the focus between the filterInput and the wrapper elements with `up` key
|
|
1426
|
-
if (this.isWrapperActive) {
|
|
1427
|
-
return;
|
|
1428
|
-
}
|
|
1429
|
-
const isFirstNodeActive = this.treeview['navigationService']['activeIndex'] === '0';
|
|
1430
|
-
// Current focus is on the filter input => should focus the wrapper
|
|
1431
|
-
if (this.filterable && this.isFilterActive) {
|
|
1432
|
-
this.focus();
|
|
1433
|
-
// Current focus is on the treeview first node => should focus the check all checkbox if enabled
|
|
1434
|
-
}
|
|
1435
|
-
else if (this.checkAll && !this.isCheckAllActive && isFirstNodeActive) {
|
|
1436
|
-
this.checkAllInput.nativeElement.focus();
|
|
1437
|
-
// Current focus is either on the check all checkbox or the treeview's first node
|
|
1438
|
-
// => should focus either the filter input (if enabled) or the wrapper
|
|
1439
|
-
}
|
|
1440
|
-
else if (this.isCheckAllActive || isFirstNodeActive) {
|
|
1441
|
-
if (this.filterable) {
|
|
1442
|
-
this.isActionSheetExpanded ? this.actionSheetSearchBar.focus() : this.filterInput.nativeElement.focus();
|
|
1443
|
-
}
|
|
1444
|
-
else if (!this.isActionSheetExpanded) {
|
|
1445
|
-
this.focus();
|
|
1446
|
-
}
|
|
1447
|
-
}
|
|
1448
|
-
}
|
|
1449
|
-
handleDownKey(event) {
|
|
1450
|
-
if (!this.treeview) {
|
|
1451
|
-
return;
|
|
1452
|
-
}
|
|
1453
|
-
event.originalEvent.preventDefault();
|
|
1454
|
-
// Current focus is on the wrapper => should focus the filter input
|
|
1455
|
-
if (this.filterable && this.isWrapperActive) {
|
|
1456
|
-
this.filterInput.nativeElement.focus();
|
|
1457
|
-
// Current focus is on the wrapper/filter input => should focus check all checkbox if enabled
|
|
1458
|
-
}
|
|
1459
|
-
else if (this.checkAll && (this.isWrapperActive || this.isFilterActive)) {
|
|
1460
|
-
this.checkAllInput.nativeElement.focus();
|
|
1461
|
-
// Should focus the treeview if filterable and check all are disabled
|
|
1462
|
-
}
|
|
1463
|
-
else if (!this.treeview.isActive) {
|
|
1464
|
-
this.treeview.focus();
|
|
1465
|
-
}
|
|
1466
|
-
this.focusedTagIndex = undefined;
|
|
1467
|
-
}
|
|
1468
|
-
handleRightKey(event) {
|
|
1469
|
-
event.originalEvent.preventDefault();
|
|
1470
|
-
const last = this.tags.length - 1;
|
|
1471
|
-
if (this.focusedTagIndex === last) {
|
|
1472
|
-
this.focusedTagIndex = undefined;
|
|
1473
|
-
}
|
|
1474
|
-
else if (this.focusedTagIndex < last) {
|
|
1475
|
-
this.focusedTagIndex++;
|
|
1476
|
-
}
|
|
1477
|
-
else if (!this.focusedTagIndex) {
|
|
1478
|
-
this.focusedTagIndex = 0;
|
|
1479
|
-
}
|
|
1480
|
-
}
|
|
1481
|
-
handleLeftKey(event) {
|
|
1482
|
-
event.originalEvent.preventDefault();
|
|
1483
|
-
if (this.focusedTagIndex === undefined || this.focusedTagIndex < 0) {
|
|
1484
|
-
this.focusedTagIndex = this.tags.length - 1;
|
|
1485
|
-
}
|
|
1486
|
-
else if (this.focusedTagIndex !== 0) {
|
|
1487
|
-
this.focusedTagIndex--;
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
handleEnd(event) {
|
|
1491
|
-
event.originalEvent.preventDefault();
|
|
1492
|
-
this.focusedTagIndex = this.tags.length - 1;
|
|
1493
|
-
}
|
|
1494
|
-
handleHome(event) {
|
|
1495
|
-
event.originalEvent.preventDefault();
|
|
1496
|
-
this.focusedTagIndex = 0;
|
|
1497
|
-
}
|
|
1498
|
-
handleBackspace() {
|
|
1499
|
-
if (this.focusedTagIndex !== undefined) {
|
|
1500
|
-
this.handleDelete();
|
|
1501
|
-
}
|
|
1502
|
-
else {
|
|
1503
|
-
const tag = this.tags[this.tags.length - 1];
|
|
1504
|
-
const index = this.tags.length - 1;
|
|
1505
|
-
this.handleRemoveTag({ tag, index });
|
|
1506
|
-
}
|
|
1507
|
-
}
|
|
1508
|
-
handleDelete() {
|
|
1509
|
-
const tag = this.tags[this.focusedTagIndex];
|
|
1510
|
-
const index = this.focusedTagIndex;
|
|
1511
|
-
this.handleRemoveTag({ tag, index });
|
|
1512
|
-
if (this.focusedTagIndex === this.tags.length) {
|
|
1513
|
-
this.focusedTagIndex = undefined;
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1516
|
-
unsubscribeEvents() {
|
|
1517
|
-
this.subs.unsubscribe();
|
|
1518
|
-
this.unSubscribeFocusEvents();
|
|
1519
|
-
}
|
|
1520
|
-
/**
|
|
1521
|
-
* Remove the `TreeView` from the tab order, otherwise a focus loop between the page elements will occur
|
|
1522
|
-
* and the user will not be able to tab to the rest of the browser elements
|
|
1523
|
-
*/
|
|
1524
|
-
removeTreeViewFromTabOrder() {
|
|
1525
|
-
const nodes = this.treeview.element.nativeElement.querySelectorAll('li');
|
|
1526
|
-
nodes.forEach(item => {
|
|
1527
|
-
if (item.getAttribute('tabindex') === '0') {
|
|
1528
|
-
this.lastNodeOnFocus = item;
|
|
1529
|
-
this.lastNodeOnFocus.setAttribute('tabindex', '-1');
|
|
1530
|
-
}
|
|
1531
|
-
});
|
|
1532
|
-
}
|
|
1533
|
-
setState() {
|
|
1534
|
-
if (isPresent(this.dataItems) && isPresent(this.valueField)) {
|
|
1535
|
-
this.setTags();
|
|
1536
|
-
this.checkedItems = this.dataItems.slice();
|
|
1537
|
-
}
|
|
1538
|
-
this.cdr.markForCheck();
|
|
1539
|
-
}
|
|
1540
|
-
setTags() {
|
|
1541
|
-
const source = this.dataItems.map(item => item.dataItem);
|
|
1542
|
-
this.tags = this.tagMapper(source);
|
|
1543
|
-
this.disabledIndices = this.disabledItemsMapper();
|
|
1544
|
-
// Create a mapping of tags to position indices
|
|
1545
|
-
const tagIndexMap = new Map(this.tags.map((tag, index) => [JSON.stringify(tag), index]));
|
|
1546
|
-
// Modify dataItems by adding a property to hold the item's position as displayed in the tags
|
|
1547
|
-
this.dataItems.forEach(item => {
|
|
1548
|
-
const serializedDataItem = JSON.stringify(item.dataItem);
|
|
1549
|
-
item.tagPositionIndex = tagIndexMap.has(serializedDataItem)
|
|
1550
|
-
? tagIndexMap.get(serializedDataItem) // Use the index from tags if it exists
|
|
1551
|
-
: null; // Assign a null value if the dataItem is not visible in the tags
|
|
1552
|
-
});
|
|
1553
|
-
}
|
|
1554
|
-
updateValue(value) {
|
|
1555
|
-
const newValue = this.valuePrimitive ?
|
|
1556
|
-
value.map(item => valueFrom(item, this.valueField)) :
|
|
1557
|
-
value.map(item => item.dataItem);
|
|
1558
|
-
this.value = newValue;
|
|
1559
|
-
this.emitValueChange(this.value);
|
|
1560
|
-
}
|
|
1561
|
-
/**
|
|
1562
|
-
* @hidden
|
|
1563
|
-
*/
|
|
1564
|
-
onChildrenLoaded() {
|
|
1565
|
-
setTimeout(() => {
|
|
1566
|
-
if (this.popupRef) {
|
|
1567
|
-
this._searchableNodes = getSearchableItems(this.treeViewId, this.popupRef.popupElement);
|
|
1568
|
-
}
|
|
1569
|
-
if (this.isActionSheetExpanded) {
|
|
1570
|
-
this._searchableNodes = getSearchableItems(this.treeViewId, this.actionSheet.element.nativeElement);
|
|
1571
|
-
}
|
|
1572
|
-
});
|
|
1573
|
-
}
|
|
1574
|
-
/**
|
|
1575
|
-
* @hidden
|
|
1576
|
-
*
|
|
1577
|
-
* Determines which of the provided tags should be disabled and stores their position indices
|
|
1578
|
-
*/
|
|
1579
|
-
disabledItemsMapper() {
|
|
1580
|
-
return new Set(this.dataItems.reduce((indices, item, index) => {
|
|
1581
|
-
if (this.itemDisabled(item.dataItem, item.index)) {
|
|
1582
|
-
indices.push(index);
|
|
1583
|
-
}
|
|
1584
|
-
return indices;
|
|
1585
|
-
}, []));
|
|
1586
|
-
}
|
|
1587
|
-
setComponentClasses() {
|
|
1588
|
-
if (this.size !== 'none') {
|
|
1589
|
-
this.renderer.addClass(this.wrapper.nativeElement, getSizeClass('input', this.size));
|
|
1590
|
-
}
|
|
1591
|
-
if (this.rounded !== 'none') {
|
|
1592
|
-
this.renderer.addClass(this.wrapper.nativeElement, getRoundedClass(this.rounded));
|
|
1593
|
-
}
|
|
1594
|
-
if (this.fillMode !== 'none') {
|
|
1595
|
-
this.renderer.addClass(this.wrapper.nativeElement, getFillModeClass('input', this.fillMode));
|
|
1596
|
-
}
|
|
1597
|
-
}
|
|
1598
|
-
removeParents(parent) {
|
|
1599
|
-
let currentParent = parent;
|
|
1600
|
-
const nodes = [];
|
|
1601
|
-
while (currentParent) {
|
|
1602
|
-
nodes.push(currentParent.item);
|
|
1603
|
-
currentParent = currentParent.parent;
|
|
1604
|
-
}
|
|
1605
|
-
return nodes;
|
|
1606
|
-
}
|
|
1607
|
-
/**
|
|
1608
|
-
* Creates an internal map of the available tree items to be used as a reference
|
|
1609
|
-
* to retrieve the item's children/parent and determine the checked sate
|
|
1610
|
-
*/
|
|
1611
|
-
registerLookupItems(data, parentItem = null, levelIndex = 0) {
|
|
1612
|
-
if (!isPresent(data) || data.length === 0) {
|
|
1613
|
-
return;
|
|
1614
|
-
}
|
|
1615
|
-
const parentIndex = nodeIndex(parentItem);
|
|
1616
|
-
const treeItems = data.map((node) => buildTreeItem(node, this.valueField, levelIndex));
|
|
1617
|
-
if (isPresent(parentItem)) {
|
|
1618
|
-
this.lookup.registerChildren(parentIndex, treeItems);
|
|
1619
|
-
}
|
|
1620
|
-
treeItems.forEach(item => {
|
|
1621
|
-
this.lookup.registerItem(item, parentItem);
|
|
1622
|
-
if (!this.loadOnDemand) {
|
|
1623
|
-
this.registerChildLookupItems(item, levelIndex);
|
|
1624
|
-
}
|
|
1625
|
-
});
|
|
1626
|
-
}
|
|
1627
|
-
registerChildLookupItems(item, levelIndex) {
|
|
1628
|
-
if (this.hasChildren(item.dataItem)) {
|
|
1629
|
-
this.children(item.dataItem)
|
|
1630
|
-
.subscribe(children => {
|
|
1631
|
-
const index = this.isHeterogeneous ? levelIndex + 1 : 0;
|
|
1632
|
-
this.registerLookupItems(children, item, index);
|
|
1633
|
-
});
|
|
1634
|
-
}
|
|
1635
|
-
}
|
|
1636
|
-
closeActionSheet() {
|
|
1637
|
-
this.wrapper.nativeElement.focus();
|
|
1638
|
-
this.actionSheet.toggle(false);
|
|
1639
|
-
this.renderer.removeAttribute(this.wrapper.nativeElement, 'aria-controls');
|
|
1640
|
-
this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-expanded', 'false');
|
|
1641
|
-
this.clearFilter();
|
|
1642
|
-
this.closed.emit();
|
|
1643
|
-
}
|
|
1644
|
-
openActionSheet() {
|
|
1645
|
-
this.actionSheet.toggle(true);
|
|
1646
|
-
this.adaptiveTitle = setActionSheetTitle(this.wrapper, this.adaptiveTitle);
|
|
1647
|
-
this.cdr.detectChanges();
|
|
1648
|
-
this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-controls', this.treeViewId);
|
|
1649
|
-
this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-expanded', 'true');
|
|
1650
|
-
this.cdr.detectChanges();
|
|
1651
|
-
this.opened.emit();
|
|
1652
|
-
}
|
|
1653
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MultiSelectTreeComponent, deps: [{ token: i0.Injector }, { token: i0.ElementRef }, { token: i1.PopupService }, { token: i0.Renderer2 }, { token: i2.NavigationService }, { token: i0.NgZone }, { token: i3.LocalizationService }, { token: i0.ChangeDetectorRef }, { token: i4.MultiSelectTreeLookupService }, { token: i5.AdaptiveService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1654
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: MultiSelectTreeComponent, isStandalone: true, selector: "kendo-multiselecttree", inputs: { adaptiveMode: "adaptiveMode", adaptiveTitle: "adaptiveTitle", adaptiveSubtitle: "adaptiveSubtitle", tabindex: "tabindex", size: "size", rounded: "rounded", fillMode: "fillMode", popupSettings: "popupSettings", checkableSettings: "checkableSettings", data: "data", value: "value", dataItems: "dataItems", textField: "textField", valueField: "valueField", valueDepth: "valueDepth", loading: "loading", placeholder: "placeholder", listHeight: "listHeight", disabled: "disabled", readonly: "readonly", valuePrimitive: "valuePrimitive", loadOnDemand: "loadOnDemand", focusableId: "focusableId", clearButton: "clearButton", filterable: "filterable", checkAll: "checkAll", hasChildren: "hasChildren", fetchChildren: "fetchChildren", isNodeExpanded: "isNodeExpanded", isNodeVisible: "isNodeVisible", itemDisabled: "itemDisabled", tagMapper: "tagMapper" }, outputs: { onFocus: "focus", onBlur: "blur", open: "open", opened: "opened", close: "close", closed: "closed", nodeExpand: "nodeExpand", nodeCollapse: "nodeCollapse", valueChange: "valueChange", removeTag: "removeTag", filterChange: "filterChange" }, host: { properties: { "class.k-multiselecttree": "this.hostClasses", "class.k-input": "this.hostClasses", "class.k-disabled": "this.isDisabled", "attr.aria-disabled": "this.isDisabled", "attr.aria-autocomplete": "this.hostAriaAutocomplete", "class.k-loading": "this.isLoading", "attr.aria-invalid": "this.hostAriaInvalid", "attr.aria-busy": "this.isBusy", "attr.id": "this.id", "attr.dir": "this.direction", "attr.tabindex": "this.hostTabIndex", "attr.role": "this.role", "attr.aria-haspopup": "this.ariaHasPopup", "attr.readonly": "this.isReadonly", "attr.aria-describedby": "this.ariaDescribedBy", "attr.aria-activedescendant": "this.ariaActiveDescendant", "class.k-readonly": "this.readonly" } }, providers: [
|
|
1655
|
-
LocalizationService,
|
|
1656
|
-
NavigationService,
|
|
1657
|
-
DataService,
|
|
1658
|
-
DisabledItemsService,
|
|
1659
|
-
SelectionService,
|
|
1660
|
-
MultiSelectTreeLookupService,
|
|
1661
|
-
{
|
|
1662
|
-
provide: L10N_PREFIX,
|
|
1663
|
-
useValue: 'kendo.multiselecttree'
|
|
1664
|
-
},
|
|
1665
|
-
{
|
|
1666
|
-
multi: true,
|
|
1667
|
-
provide: NG_VALUE_ACCESSOR,
|
|
1668
|
-
useExisting: forwardRef(() => MultiSelectTreeComponent)
|
|
1669
|
-
},
|
|
1670
|
-
{
|
|
1671
|
-
provide: DataBoundComponent,
|
|
1672
|
-
useExisting: forwardRef(() => MultiSelectTreeComponent)
|
|
1673
|
-
},
|
|
1674
|
-
{
|
|
1675
|
-
provide: ExpandableComponent,
|
|
1676
|
-
useExisting: forwardRef(() => MultiSelectTreeComponent)
|
|
1677
|
-
},
|
|
1678
|
-
{
|
|
1679
|
-
provide: KendoInput,
|
|
1680
|
-
useExisting: forwardRef(() => MultiSelectTreeComponent)
|
|
1681
|
-
}
|
|
1682
|
-
], queries: [{ propertyName: "headerTemplate", first: true, predicate: HeaderTemplateDirective, descendants: true }, { propertyName: "footerTemplate", first: true, predicate: FooterTemplateDirective, descendants: true }, { propertyName: "nodeTemplate", first: true, predicate: NodeTemplateDirective, descendants: true }, { propertyName: "noDataTemplate", first: true, predicate: NoDataTemplateDirective, descendants: true }, { propertyName: "tagTemplate", first: true, predicate: TagTemplateDirective, descendants: true }, { propertyName: "groupTagTemplate", first: true, predicate: GroupTagTemplateDirective, descendants: true }], viewQueries: [{ propertyName: "adaptiveRendererComponent", first: true, predicate: AdaptiveRendererComponent, descendants: true }, { propertyName: "popupTemplate", first: true, predicate: ["popupTemplate"], descendants: true, static: true }, { propertyName: "container", first: true, predicate: ["container"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "treeview", first: true, predicate: ["treeview"], descendants: true }, { propertyName: "filterInput", first: true, predicate: ["filterInput"], descendants: true }, { propertyName: "checkAllInput", first: true, predicate: ["checkAllInput"], descendants: true }], exportAs: ["kendoMultiSelectTree"], usesOnChanges: true, ngImport: i0, template: `
|
|
1683
|
-
<ng-container kendoMultiSelectTreeLocalizedMessages
|
|
1684
|
-
i18n-noDataText="kendo.multiselecttree.noDataText|The text displayed in the popup when there are no items"
|
|
1685
|
-
noDataText="NO DATA FOUND"
|
|
1686
|
-
|
|
1687
|
-
i18n-clearTitle="kendo.multiselecttree.clearTitle|The title of the clear button"
|
|
1688
|
-
clearTitle="clear"
|
|
1689
|
-
|
|
1690
|
-
i18n-checkAllText="kendo.multiselecttree.checkAllText|The text displayed for the check-all checkbox"
|
|
1691
|
-
checkAllText="Check all"
|
|
1692
|
-
|
|
1693
|
-
i18n-filterInputLabel="kendo.multiselecttree.filterInputLabel|The text set as aria-label on the filter input"
|
|
1694
|
-
filterInputLabel="Filter"
|
|
1695
|
-
|
|
1696
|
-
i18n-popupLabel="kendo.multiselecttree.popupLabel|The label of the popup element that contains the list of options when its role is 'region'"
|
|
1697
|
-
popupLabel="Options list"
|
|
1698
|
-
|
|
1699
|
-
i18n-adaptiveCloseButtonTitle="kendo.multiselecttree.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"
|
|
1700
|
-
adaptiveCloseButtonTitle="Close"
|
|
1701
|
-
|
|
1702
|
-
i18n-filterInputPlaceholder="kendo.multiselecttree.filterInputPlaceholder|The text for the input's placeholder when filtering is enabled"
|
|
1703
|
-
filterInputPlaceholder="Filter"
|
|
1704
|
-
>
|
|
1705
|
-
</ng-container>
|
|
1706
|
-
<kendo-taglist
|
|
1707
|
-
class="k-input-values"
|
|
1708
|
-
[size]="size"
|
|
1709
|
-
[rounded]="rounded"
|
|
1710
|
-
[fillMode]="fillMode"
|
|
1711
|
-
[id]="tagListId"
|
|
1712
|
-
[tags]="tags"
|
|
1713
|
-
[focused]="focusedTagIndex"
|
|
1714
|
-
[textField]="textField"
|
|
1715
|
-
[valueField]="valueField"
|
|
1716
|
-
[valueDepth]="valueDepth"
|
|
1717
|
-
[disabled]="disabled"
|
|
1718
|
-
[tagPrefix]="tagPrefix"
|
|
1719
|
-
[template]="tagTemplate"
|
|
1720
|
-
[groupTemplate]="groupTagTemplate"
|
|
1721
|
-
[disabledIndices]="disabledIndices"
|
|
1722
|
-
(removeTag)="handleRemoveTag($event)"
|
|
1723
|
-
>
|
|
1724
|
-
</kendo-taglist>
|
|
1725
|
-
<span class="k-input-inner">
|
|
1726
|
-
@if (!tags || !tags.length) {
|
|
1727
|
-
<span
|
|
1728
|
-
class="k-input-value-text"
|
|
1729
|
-
>
|
|
1730
|
-
{{ placeholder }}
|
|
1731
|
-
</span>
|
|
1732
|
-
}
|
|
1733
|
-
</span>
|
|
1734
|
-
@if (!disabled && !loading && !readonly && clearButton && tags?.length) {
|
|
1735
|
-
<span
|
|
1736
|
-
class="k-clear-value"
|
|
1737
|
-
[attr.title]="messageFor('clearTitle')"
|
|
1738
|
-
role="button"
|
|
1739
|
-
tabindex="-1"
|
|
1740
|
-
(click)="clearAll($event)"
|
|
1741
|
-
>
|
|
1742
|
-
<kendo-icon-wrapper
|
|
1743
|
-
class="k-icon"
|
|
1744
|
-
name="x"
|
|
1745
|
-
[svgIcon]="xIcon"
|
|
1746
|
-
>
|
|
1747
|
-
</kendo-icon-wrapper>
|
|
1748
|
-
</span>
|
|
1749
|
-
}
|
|
1750
|
-
@if (loading) {
|
|
1751
|
-
<span
|
|
1752
|
-
class="k-icon k-i-loading k-input-loading-icon"
|
|
1753
|
-
>
|
|
1754
|
-
</span>
|
|
1755
|
-
}
|
|
1756
|
-
<ng-template #popupTemplate>
|
|
1757
|
-
<ng-container *ngTemplateOutlet="sharedPopupActionSheetTemplate"></ng-container>
|
|
1758
|
-
</ng-template>
|
|
1759
|
-
<ng-container #container></ng-container>
|
|
1760
|
-
|
|
1761
|
-
<kendo-adaptive-renderer
|
|
1762
|
-
[sharedPopupActionSheetTemplate]="sharedPopupActionSheetTemplate"
|
|
1763
|
-
[title]="adaptiveTitle"
|
|
1764
|
-
[showTextInput]="filterable"
|
|
1765
|
-
[subtitle]="adaptiveSubtitle"
|
|
1766
|
-
(closePopup)="togglePopup(false)"
|
|
1767
|
-
(textInputChange)="onFilterChange($event)"
|
|
1768
|
-
[searchBarValue]="filter"
|
|
1769
|
-
[placeholder]="placeholder"
|
|
1770
|
-
[filterable]="filterable">
|
|
1771
|
-
</kendo-adaptive-renderer>
|
|
1772
|
-
|
|
1773
|
-
<ng-template #sharedPopupActionSheetTemplate>
|
|
1774
|
-
@if (filterable && !isActionSheetExpanded) {
|
|
1775
|
-
<div
|
|
1776
|
-
class="k-list-filter"
|
|
1777
|
-
>
|
|
1778
|
-
<span
|
|
1779
|
-
class="k-textbox k-input"
|
|
1780
|
-
[ngClass]="filterInputClasses"
|
|
1781
|
-
>
|
|
1782
|
-
<span class="k-input-prefix">
|
|
1783
|
-
<kendo-icon-wrapper
|
|
1784
|
-
class="k-icon"
|
|
1785
|
-
name="search"
|
|
1786
|
-
[svgIcon]="searchIcon"
|
|
1787
|
-
>
|
|
1788
|
-
</kendo-icon-wrapper>
|
|
1789
|
-
</span>
|
|
1790
|
-
<input
|
|
1791
|
-
#filterInput
|
|
1792
|
-
(input)="handleFilterInputChange($event.target)"
|
|
1793
|
-
[filterInput]="filterable && !touchEnabled"
|
|
1794
|
-
[attr.aria-label]="messageFor('filterInputLabel')"
|
|
1795
|
-
(keydown)="handleKeydown($event, filterInput)"
|
|
1796
|
-
[value]="filter"
|
|
1797
|
-
class="k-input-inner"
|
|
1798
|
-
role="searchbox"
|
|
1799
|
-
tabindex="0"
|
|
1800
|
-
aria-disabled="false"
|
|
1801
|
-
aria-readonly="false"
|
|
1802
|
-
[kendoEventsOutsideAngular]="{
|
|
1803
|
-
blur: handleBlur
|
|
1804
|
-
}"
|
|
1805
|
-
[scope]="this"
|
|
1806
|
-
>
|
|
1807
|
-
</span>
|
|
1808
|
-
</div>
|
|
1809
|
-
}
|
|
1810
|
-
<!--header template-->
|
|
1811
|
-
@if (headerTemplate) {
|
|
1812
|
-
<ng-template
|
|
1813
|
-
[templateContext]="{
|
|
1814
|
-
templateRef: headerTemplate?.templateRef
|
|
1815
|
-
}">
|
|
1816
|
-
</ng-template>
|
|
1817
|
-
}
|
|
1818
|
-
@if (checkAll) {
|
|
1819
|
-
<div class="k-check-all">
|
|
1820
|
-
<span class="k-checkbox-wrap">
|
|
1821
|
-
<input
|
|
1822
|
-
#checkAllInput
|
|
1823
|
-
[checkAll]="!filterable && !touchEnabled"
|
|
1824
|
-
type="checkbox"
|
|
1825
|
-
class="k-checkbox"
|
|
1826
|
-
[ngClass]="checkAllCheckboxClasses"
|
|
1827
|
-
role="checkbox"
|
|
1828
|
-
tabindex="0"
|
|
1829
|
-
aria-disabled="false"
|
|
1830
|
-
aria-readonly="false"
|
|
1831
|
-
[treeview]="treeview"
|
|
1832
|
-
[checkedItems]="checkedItems"
|
|
1833
|
-
[valueField]="valueField"
|
|
1834
|
-
[lastAction]="lastAction"
|
|
1835
|
-
(checkedItemsChange)="handleCheckedItemsChange($event)"
|
|
1836
|
-
(keydown)="handleKeydown($event)"
|
|
1837
|
-
[kendoEventsOutsideAngular]="{
|
|
1838
|
-
blur: handleBlur
|
|
1839
|
-
}"
|
|
1840
|
-
[scope]="this"
|
|
1841
|
-
>
|
|
1842
|
-
</span>
|
|
1843
|
-
<span
|
|
1844
|
-
class="k-checkbox-label"
|
|
1845
|
-
(click)="toggleCheckAll()"
|
|
1846
|
-
(mousedown)="$event.preventDefault()"
|
|
1847
|
-
>
|
|
1848
|
-
{{ messageFor('checkAllText') }}
|
|
1849
|
-
</span>
|
|
1850
|
-
</div>
|
|
1851
|
-
}
|
|
1852
|
-
<kendo-treeview
|
|
1853
|
-
#treeview
|
|
1854
|
-
[size]="windowSize !== 'large' ? 'large' : size"
|
|
1855
|
-
[attr.id]="treeViewId"
|
|
1856
|
-
[nodes]="data"
|
|
1857
|
-
[style.maxHeight.px]="listHeight"
|
|
1858
|
-
[animate]="false"
|
|
1859
|
-
kendoMultiSelectTreeCheckable
|
|
1860
|
-
[isHeterogeneous]="isHeterogeneous"
|
|
1861
|
-
[checkable]="checkableSettings"
|
|
1862
|
-
[checkedItems]="checkedItems"
|
|
1863
|
-
[valueField]="valueField"
|
|
1864
|
-
[textField]="textField"
|
|
1865
|
-
[children]="children"
|
|
1866
|
-
[hasChildren]="hasChildren"
|
|
1867
|
-
[isExpanded]="isNodeExpanded"
|
|
1868
|
-
[isDisabled]="itemDisabled"
|
|
1869
|
-
[nodeTemplate]="nodeTemplate"
|
|
1870
|
-
[loadOnDemand]="loadOnDemand"
|
|
1871
|
-
[filter]="filter"
|
|
1872
|
-
[isVisible]="isNodeVisible"
|
|
1873
|
-
(keydown)="handleKeydown($event)"
|
|
1874
|
-
(nodeClick)="handleNodeClick($event)"
|
|
1875
|
-
(expand)="nodeExpand.emit($event)"
|
|
1876
|
-
(collapse)="nodeCollapse.emit($event)"
|
|
1877
|
-
(checkedItemsChange)="handleCheckedItemsChange($event)"
|
|
1878
|
-
[kendoEventsOutsideAngular]="{
|
|
1879
|
-
focusout: handleBlur
|
|
1880
|
-
}"
|
|
1881
|
-
[scope]="this"
|
|
1882
|
-
(childrenLoaded)="onChildrenLoaded()"
|
|
1883
|
-
>
|
|
1884
|
-
</kendo-treeview>
|
|
1885
|
-
<!--footer template-->
|
|
1886
|
-
@if (footerTemplate) {
|
|
1887
|
-
<ng-template
|
|
1888
|
-
[templateContext]="{
|
|
1889
|
-
templateRef: footerTemplate?.templateRef
|
|
1890
|
-
}">
|
|
1891
|
-
</ng-template>
|
|
1892
|
-
}
|
|
1893
|
-
<!--no-data template-->
|
|
1894
|
-
@if (!data || data?.length === 0 || allNodesHidden) {
|
|
1895
|
-
<div class="k-no-data">
|
|
1896
|
-
@if (noDataTemplate) {
|
|
1897
|
-
<ng-template
|
|
1898
|
-
[templateContext]="{
|
|
1899
|
-
templateRef: noDataTemplate?.templateRef
|
|
1900
|
-
}">
|
|
1901
|
-
</ng-template>
|
|
1902
|
-
}
|
|
1903
|
-
@if (!noDataTemplate) {
|
|
1904
|
-
<div>{{ messageFor('noDataText') }}</div>
|
|
1905
|
-
}
|
|
1906
|
-
</div>
|
|
1907
|
-
}
|
|
1908
|
-
</ng-template>
|
|
1909
|
-
|
|
1910
|
-
@if (isOpen || isAdaptiveModeEnabled) {
|
|
1911
|
-
<kendo-resize-sensor (resize)="onResize()"></kendo-resize-sensor>
|
|
1912
|
-
}
|
|
1913
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "\n [kendoDropDownListLocalizedMessages],\n [kendoDropDownTreeLocalizedMessages],\n [kendoComboBoxLocalizedMessages],\n [kendoMultiColumnComboBoxLocalizedMessages],\n [kendoAutoCompleteLocalizedMessages],\n [kendoMultiSelectLocalizedMessages],\n [kendoMultiSelectTreeLocalizedMessages]\n " }, { 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: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: FilterInputDirective, selector: "[filterInput]", inputs: ["filterInput"] }, { kind: "directive", type: EventsOutsideAngularDirective, selector: "[kendoEventsOutsideAngular]", inputs: ["kendoEventsOutsideAngular", "scope"] }, { kind: "directive", type: TemplateContextDirective, selector: "[templateContext]", inputs: ["templateContext"] }, { kind: "directive", type: CheckAllDirective, selector: "[checkAll]", inputs: ["lastAction", "treeview", "checkedItems", "valueField", "checkAll"], outputs: ["checkedItemsChange"] }, { kind: "component", type: TreeViewComponent, selector: "kendo-treeview", inputs: ["filterInputPlaceholder", "expandDisabledNodes", "animate", "nodeTemplate", "loadMoreButtonTemplate", "trackBy", "nodes", "textField", "hasChildren", "isChecked", "isDisabled", "hasCheckbox", "isExpanded", "isSelected", "isVisible", "navigable", "children", "loadOnDemand", "filterable", "filter", "size", "disableParentNodesOnly"], outputs: ["childrenLoaded", "blur", "focus", "expand", "collapse", "nodeDragStart", "nodeDrag", "filterStateChange", "nodeDrop", "nodeDragEnd", "addItem", "removeItem", "checkedChange", "selectionChange", "filterChange", "nodeClick", "nodeDblClick"], exportAs: ["kendoTreeView"] }, { kind: "directive", type: CheckDirective, selector: "[kendoMultiSelectTreeCheckable]", inputs: ["checkable", "valueField", "checkedItems"], outputs: ["checkedItemsChange"] }, { kind: "component", type: ResizeSensorComponent, selector: "kendo-resize-sensor", inputs: ["rateLimit"], outputs: ["resize"] }] });
|
|
1914
|
-
}
|
|
1915
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MultiSelectTreeComponent, decorators: [{
|
|
1916
|
-
type: Component,
|
|
1917
|
-
args: [{
|
|
1918
|
-
exportAs: 'kendoMultiSelectTree',
|
|
1919
|
-
providers: [
|
|
1920
|
-
LocalizationService,
|
|
1921
|
-
NavigationService,
|
|
1922
|
-
DataService,
|
|
1923
|
-
DisabledItemsService,
|
|
1924
|
-
SelectionService,
|
|
1925
|
-
MultiSelectTreeLookupService,
|
|
1926
|
-
{
|
|
1927
|
-
provide: L10N_PREFIX,
|
|
1928
|
-
useValue: 'kendo.multiselecttree'
|
|
1929
|
-
},
|
|
1930
|
-
{
|
|
1931
|
-
multi: true,
|
|
1932
|
-
provide: NG_VALUE_ACCESSOR,
|
|
1933
|
-
useExisting: forwardRef(() => MultiSelectTreeComponent)
|
|
1934
|
-
},
|
|
1935
|
-
{
|
|
1936
|
-
provide: DataBoundComponent,
|
|
1937
|
-
useExisting: forwardRef(() => MultiSelectTreeComponent)
|
|
1938
|
-
},
|
|
1939
|
-
{
|
|
1940
|
-
provide: ExpandableComponent,
|
|
1941
|
-
useExisting: forwardRef(() => MultiSelectTreeComponent)
|
|
1942
|
-
},
|
|
1943
|
-
{
|
|
1944
|
-
provide: KendoInput,
|
|
1945
|
-
useExisting: forwardRef(() => MultiSelectTreeComponent)
|
|
1946
|
-
}
|
|
1947
|
-
],
|
|
1948
|
-
selector: 'kendo-multiselecttree',
|
|
1949
|
-
template: `
|
|
1950
|
-
<ng-container kendoMultiSelectTreeLocalizedMessages
|
|
1951
|
-
i18n-noDataText="kendo.multiselecttree.noDataText|The text displayed in the popup when there are no items"
|
|
1952
|
-
noDataText="NO DATA FOUND"
|
|
1953
|
-
|
|
1954
|
-
i18n-clearTitle="kendo.multiselecttree.clearTitle|The title of the clear button"
|
|
1955
|
-
clearTitle="clear"
|
|
1956
|
-
|
|
1957
|
-
i18n-checkAllText="kendo.multiselecttree.checkAllText|The text displayed for the check-all checkbox"
|
|
1958
|
-
checkAllText="Check all"
|
|
1959
|
-
|
|
1960
|
-
i18n-filterInputLabel="kendo.multiselecttree.filterInputLabel|The text set as aria-label on the filter input"
|
|
1961
|
-
filterInputLabel="Filter"
|
|
1962
|
-
|
|
1963
|
-
i18n-popupLabel="kendo.multiselecttree.popupLabel|The label of the popup element that contains the list of options when its role is 'region'"
|
|
1964
|
-
popupLabel="Options list"
|
|
1965
|
-
|
|
1966
|
-
i18n-adaptiveCloseButtonTitle="kendo.multiselecttree.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"
|
|
1967
|
-
adaptiveCloseButtonTitle="Close"
|
|
1968
|
-
|
|
1969
|
-
i18n-filterInputPlaceholder="kendo.multiselecttree.filterInputPlaceholder|The text for the input's placeholder when filtering is enabled"
|
|
1970
|
-
filterInputPlaceholder="Filter"
|
|
1971
|
-
>
|
|
1972
|
-
</ng-container>
|
|
1973
|
-
<kendo-taglist
|
|
1974
|
-
class="k-input-values"
|
|
1975
|
-
[size]="size"
|
|
1976
|
-
[rounded]="rounded"
|
|
1977
|
-
[fillMode]="fillMode"
|
|
1978
|
-
[id]="tagListId"
|
|
1979
|
-
[tags]="tags"
|
|
1980
|
-
[focused]="focusedTagIndex"
|
|
1981
|
-
[textField]="textField"
|
|
1982
|
-
[valueField]="valueField"
|
|
1983
|
-
[valueDepth]="valueDepth"
|
|
1984
|
-
[disabled]="disabled"
|
|
1985
|
-
[tagPrefix]="tagPrefix"
|
|
1986
|
-
[template]="tagTemplate"
|
|
1987
|
-
[groupTemplate]="groupTagTemplate"
|
|
1988
|
-
[disabledIndices]="disabledIndices"
|
|
1989
|
-
(removeTag)="handleRemoveTag($event)"
|
|
1990
|
-
>
|
|
1991
|
-
</kendo-taglist>
|
|
1992
|
-
<span class="k-input-inner">
|
|
1993
|
-
@if (!tags || !tags.length) {
|
|
1994
|
-
<span
|
|
1995
|
-
class="k-input-value-text"
|
|
1996
|
-
>
|
|
1997
|
-
{{ placeholder }}
|
|
1998
|
-
</span>
|
|
1999
|
-
}
|
|
2000
|
-
</span>
|
|
2001
|
-
@if (!disabled && !loading && !readonly && clearButton && tags?.length) {
|
|
2002
|
-
<span
|
|
2003
|
-
class="k-clear-value"
|
|
2004
|
-
[attr.title]="messageFor('clearTitle')"
|
|
2005
|
-
role="button"
|
|
2006
|
-
tabindex="-1"
|
|
2007
|
-
(click)="clearAll($event)"
|
|
2008
|
-
>
|
|
2009
|
-
<kendo-icon-wrapper
|
|
2010
|
-
class="k-icon"
|
|
2011
|
-
name="x"
|
|
2012
|
-
[svgIcon]="xIcon"
|
|
2013
|
-
>
|
|
2014
|
-
</kendo-icon-wrapper>
|
|
2015
|
-
</span>
|
|
2016
|
-
}
|
|
2017
|
-
@if (loading) {
|
|
2018
|
-
<span
|
|
2019
|
-
class="k-icon k-i-loading k-input-loading-icon"
|
|
2020
|
-
>
|
|
2021
|
-
</span>
|
|
2022
|
-
}
|
|
2023
|
-
<ng-template #popupTemplate>
|
|
2024
|
-
<ng-container *ngTemplateOutlet="sharedPopupActionSheetTemplate"></ng-container>
|
|
2025
|
-
</ng-template>
|
|
2026
|
-
<ng-container #container></ng-container>
|
|
2027
|
-
|
|
2028
|
-
<kendo-adaptive-renderer
|
|
2029
|
-
[sharedPopupActionSheetTemplate]="sharedPopupActionSheetTemplate"
|
|
2030
|
-
[title]="adaptiveTitle"
|
|
2031
|
-
[showTextInput]="filterable"
|
|
2032
|
-
[subtitle]="adaptiveSubtitle"
|
|
2033
|
-
(closePopup)="togglePopup(false)"
|
|
2034
|
-
(textInputChange)="onFilterChange($event)"
|
|
2035
|
-
[searchBarValue]="filter"
|
|
2036
|
-
[placeholder]="placeholder"
|
|
2037
|
-
[filterable]="filterable">
|
|
2038
|
-
</kendo-adaptive-renderer>
|
|
2039
|
-
|
|
2040
|
-
<ng-template #sharedPopupActionSheetTemplate>
|
|
2041
|
-
@if (filterable && !isActionSheetExpanded) {
|
|
2042
|
-
<div
|
|
2043
|
-
class="k-list-filter"
|
|
2044
|
-
>
|
|
2045
|
-
<span
|
|
2046
|
-
class="k-textbox k-input"
|
|
2047
|
-
[ngClass]="filterInputClasses"
|
|
2048
|
-
>
|
|
2049
|
-
<span class="k-input-prefix">
|
|
2050
|
-
<kendo-icon-wrapper
|
|
2051
|
-
class="k-icon"
|
|
2052
|
-
name="search"
|
|
2053
|
-
[svgIcon]="searchIcon"
|
|
2054
|
-
>
|
|
2055
|
-
</kendo-icon-wrapper>
|
|
2056
|
-
</span>
|
|
2057
|
-
<input
|
|
2058
|
-
#filterInput
|
|
2059
|
-
(input)="handleFilterInputChange($event.target)"
|
|
2060
|
-
[filterInput]="filterable && !touchEnabled"
|
|
2061
|
-
[attr.aria-label]="messageFor('filterInputLabel')"
|
|
2062
|
-
(keydown)="handleKeydown($event, filterInput)"
|
|
2063
|
-
[value]="filter"
|
|
2064
|
-
class="k-input-inner"
|
|
2065
|
-
role="searchbox"
|
|
2066
|
-
tabindex="0"
|
|
2067
|
-
aria-disabled="false"
|
|
2068
|
-
aria-readonly="false"
|
|
2069
|
-
[kendoEventsOutsideAngular]="{
|
|
2070
|
-
blur: handleBlur
|
|
2071
|
-
}"
|
|
2072
|
-
[scope]="this"
|
|
2073
|
-
>
|
|
2074
|
-
</span>
|
|
2075
|
-
</div>
|
|
2076
|
-
}
|
|
2077
|
-
<!--header template-->
|
|
2078
|
-
@if (headerTemplate) {
|
|
2079
|
-
<ng-template
|
|
2080
|
-
[templateContext]="{
|
|
2081
|
-
templateRef: headerTemplate?.templateRef
|
|
2082
|
-
}">
|
|
2083
|
-
</ng-template>
|
|
2084
|
-
}
|
|
2085
|
-
@if (checkAll) {
|
|
2086
|
-
<div class="k-check-all">
|
|
2087
|
-
<span class="k-checkbox-wrap">
|
|
2088
|
-
<input
|
|
2089
|
-
#checkAllInput
|
|
2090
|
-
[checkAll]="!filterable && !touchEnabled"
|
|
2091
|
-
type="checkbox"
|
|
2092
|
-
class="k-checkbox"
|
|
2093
|
-
[ngClass]="checkAllCheckboxClasses"
|
|
2094
|
-
role="checkbox"
|
|
2095
|
-
tabindex="0"
|
|
2096
|
-
aria-disabled="false"
|
|
2097
|
-
aria-readonly="false"
|
|
2098
|
-
[treeview]="treeview"
|
|
2099
|
-
[checkedItems]="checkedItems"
|
|
2100
|
-
[valueField]="valueField"
|
|
2101
|
-
[lastAction]="lastAction"
|
|
2102
|
-
(checkedItemsChange)="handleCheckedItemsChange($event)"
|
|
2103
|
-
(keydown)="handleKeydown($event)"
|
|
2104
|
-
[kendoEventsOutsideAngular]="{
|
|
2105
|
-
blur: handleBlur
|
|
2106
|
-
}"
|
|
2107
|
-
[scope]="this"
|
|
2108
|
-
>
|
|
2109
|
-
</span>
|
|
2110
|
-
<span
|
|
2111
|
-
class="k-checkbox-label"
|
|
2112
|
-
(click)="toggleCheckAll()"
|
|
2113
|
-
(mousedown)="$event.preventDefault()"
|
|
2114
|
-
>
|
|
2115
|
-
{{ messageFor('checkAllText') }}
|
|
2116
|
-
</span>
|
|
2117
|
-
</div>
|
|
2118
|
-
}
|
|
2119
|
-
<kendo-treeview
|
|
2120
|
-
#treeview
|
|
2121
|
-
[size]="windowSize !== 'large' ? 'large' : size"
|
|
2122
|
-
[attr.id]="treeViewId"
|
|
2123
|
-
[nodes]="data"
|
|
2124
|
-
[style.maxHeight.px]="listHeight"
|
|
2125
|
-
[animate]="false"
|
|
2126
|
-
kendoMultiSelectTreeCheckable
|
|
2127
|
-
[isHeterogeneous]="isHeterogeneous"
|
|
2128
|
-
[checkable]="checkableSettings"
|
|
2129
|
-
[checkedItems]="checkedItems"
|
|
2130
|
-
[valueField]="valueField"
|
|
2131
|
-
[textField]="textField"
|
|
2132
|
-
[children]="children"
|
|
2133
|
-
[hasChildren]="hasChildren"
|
|
2134
|
-
[isExpanded]="isNodeExpanded"
|
|
2135
|
-
[isDisabled]="itemDisabled"
|
|
2136
|
-
[nodeTemplate]="nodeTemplate"
|
|
2137
|
-
[loadOnDemand]="loadOnDemand"
|
|
2138
|
-
[filter]="filter"
|
|
2139
|
-
[isVisible]="isNodeVisible"
|
|
2140
|
-
(keydown)="handleKeydown($event)"
|
|
2141
|
-
(nodeClick)="handleNodeClick($event)"
|
|
2142
|
-
(expand)="nodeExpand.emit($event)"
|
|
2143
|
-
(collapse)="nodeCollapse.emit($event)"
|
|
2144
|
-
(checkedItemsChange)="handleCheckedItemsChange($event)"
|
|
2145
|
-
[kendoEventsOutsideAngular]="{
|
|
2146
|
-
focusout: handleBlur
|
|
2147
|
-
}"
|
|
2148
|
-
[scope]="this"
|
|
2149
|
-
(childrenLoaded)="onChildrenLoaded()"
|
|
2150
|
-
>
|
|
2151
|
-
</kendo-treeview>
|
|
2152
|
-
<!--footer template-->
|
|
2153
|
-
@if (footerTemplate) {
|
|
2154
|
-
<ng-template
|
|
2155
|
-
[templateContext]="{
|
|
2156
|
-
templateRef: footerTemplate?.templateRef
|
|
2157
|
-
}">
|
|
2158
|
-
</ng-template>
|
|
2159
|
-
}
|
|
2160
|
-
<!--no-data template-->
|
|
2161
|
-
@if (!data || data?.length === 0 || allNodesHidden) {
|
|
2162
|
-
<div class="k-no-data">
|
|
2163
|
-
@if (noDataTemplate) {
|
|
2164
|
-
<ng-template
|
|
2165
|
-
[templateContext]="{
|
|
2166
|
-
templateRef: noDataTemplate?.templateRef
|
|
2167
|
-
}">
|
|
2168
|
-
</ng-template>
|
|
2169
|
-
}
|
|
2170
|
-
@if (!noDataTemplate) {
|
|
2171
|
-
<div>{{ messageFor('noDataText') }}</div>
|
|
2172
|
-
}
|
|
2173
|
-
</div>
|
|
2174
|
-
}
|
|
2175
|
-
</ng-template>
|
|
2176
|
-
|
|
2177
|
-
@if (isOpen || isAdaptiveModeEnabled) {
|
|
2178
|
-
<kendo-resize-sensor (resize)="onResize()"></kendo-resize-sensor>
|
|
2179
|
-
}
|
|
2180
|
-
`,
|
|
2181
|
-
standalone: true,
|
|
2182
|
-
imports: [LocalizedMessagesDirective, TagListComponent, IconWrapperComponent, NgTemplateOutlet, AdaptiveRendererComponent, NgClass, FilterInputDirective, EventsOutsideAngularDirective, TemplateContextDirective, CheckAllDirective, TreeViewComponent, CheckDirective, ResizeSensorComponent]
|
|
2183
|
-
}]
|
|
2184
|
-
}], ctorParameters: () => [{ type: i0.Injector }, { type: i0.ElementRef }, { type: i1.PopupService }, { type: i0.Renderer2 }, { type: i2.NavigationService }, { type: i0.NgZone }, { type: i3.LocalizationService }, { type: i0.ChangeDetectorRef }, { type: i4.MultiSelectTreeLookupService }, { type: i5.AdaptiveService }], propDecorators: { hostClasses: [{
|
|
2185
|
-
type: HostBinding,
|
|
2186
|
-
args: ['class.k-multiselecttree']
|
|
2187
|
-
}, {
|
|
2188
|
-
type: HostBinding,
|
|
2189
|
-
args: ['class.k-input']
|
|
2190
|
-
}], isDisabled: [{
|
|
2191
|
-
type: HostBinding,
|
|
2192
|
-
args: ['class.k-disabled']
|
|
2193
|
-
}, {
|
|
2194
|
-
type: HostBinding,
|
|
2195
|
-
args: ['attr.aria-disabled']
|
|
2196
|
-
}], hostAriaAutocomplete: [{
|
|
2197
|
-
type: HostBinding,
|
|
2198
|
-
args: ['attr.aria-autocomplete']
|
|
2199
|
-
}], isLoading: [{
|
|
2200
|
-
type: HostBinding,
|
|
2201
|
-
args: ['class.k-loading']
|
|
2202
|
-
}], hostAriaInvalid: [{
|
|
2203
|
-
type: HostBinding,
|
|
2204
|
-
args: ['attr.aria-invalid']
|
|
2205
|
-
}], isBusy: [{
|
|
2206
|
-
type: HostBinding,
|
|
2207
|
-
args: ['attr.aria-busy']
|
|
2208
|
-
}], id: [{
|
|
2209
|
-
type: HostBinding,
|
|
2210
|
-
args: ['attr.id']
|
|
2211
|
-
}], direction: [{
|
|
2212
|
-
type: HostBinding,
|
|
2213
|
-
args: ['attr.dir']
|
|
2214
|
-
}], hostTabIndex: [{
|
|
2215
|
-
type: HostBinding,
|
|
2216
|
-
args: ['attr.tabindex']
|
|
2217
|
-
}], role: [{
|
|
2218
|
-
type: HostBinding,
|
|
2219
|
-
args: ['attr.role']
|
|
2220
|
-
}], ariaHasPopup: [{
|
|
2221
|
-
type: HostBinding,
|
|
2222
|
-
args: ['attr.aria-haspopup']
|
|
2223
|
-
}], isReadonly: [{
|
|
2224
|
-
type: HostBinding,
|
|
2225
|
-
args: ['attr.readonly']
|
|
2226
|
-
}], ariaDescribedBy: [{
|
|
2227
|
-
type: HostBinding,
|
|
2228
|
-
args: ['attr.aria-describedby']
|
|
2229
|
-
}], ariaActiveDescendant: [{
|
|
2230
|
-
type: HostBinding,
|
|
2231
|
-
args: ['attr.aria-activedescendant']
|
|
2232
|
-
}], adaptiveMode: [{
|
|
2233
|
-
type: Input
|
|
2234
|
-
}], adaptiveTitle: [{
|
|
2235
|
-
type: Input
|
|
2236
|
-
}], adaptiveSubtitle: [{
|
|
2237
|
-
type: Input
|
|
2238
|
-
}], adaptiveRendererComponent: [{
|
|
2239
|
-
type: ViewChild,
|
|
2240
|
-
args: [AdaptiveRendererComponent]
|
|
2241
|
-
}], headerTemplate: [{
|
|
2242
|
-
type: ContentChild,
|
|
2243
|
-
args: [HeaderTemplateDirective, { static: false }]
|
|
2244
|
-
}], footerTemplate: [{
|
|
2245
|
-
type: ContentChild,
|
|
2246
|
-
args: [FooterTemplateDirective, { static: false }]
|
|
2247
|
-
}], nodeTemplate: [{
|
|
2248
|
-
type: ContentChild,
|
|
2249
|
-
args: [NodeTemplateDirective, { static: false }]
|
|
2250
|
-
}], noDataTemplate: [{
|
|
2251
|
-
type: ContentChild,
|
|
2252
|
-
args: [NoDataTemplateDirective, { static: false }]
|
|
2253
|
-
}], tagTemplate: [{
|
|
2254
|
-
type: ContentChild,
|
|
2255
|
-
args: [TagTemplateDirective, { static: false }]
|
|
2256
|
-
}], groupTagTemplate: [{
|
|
2257
|
-
type: ContentChild,
|
|
2258
|
-
args: [GroupTagTemplateDirective, { static: false }]
|
|
2259
|
-
}], popupTemplate: [{
|
|
2260
|
-
type: ViewChild,
|
|
2261
|
-
args: ['popupTemplate', { static: true }]
|
|
2262
|
-
}], container: [{
|
|
2263
|
-
type: ViewChild,
|
|
2264
|
-
args: ['container', { read: ViewContainerRef, static: true }]
|
|
2265
|
-
}], treeview: [{
|
|
2266
|
-
type: ViewChild,
|
|
2267
|
-
args: ['treeview', { static: false }]
|
|
2268
|
-
}], filterInput: [{
|
|
2269
|
-
type: ViewChild,
|
|
2270
|
-
args: ['filterInput', { static: false }]
|
|
2271
|
-
}], checkAllInput: [{
|
|
2272
|
-
type: ViewChild,
|
|
2273
|
-
args: ['checkAllInput', { static: false }]
|
|
2274
|
-
}], tabindex: [{
|
|
2275
|
-
type: Input
|
|
2276
|
-
}], size: [{
|
|
2277
|
-
type: Input
|
|
2278
|
-
}], rounded: [{
|
|
2279
|
-
type: Input
|
|
2280
|
-
}], fillMode: [{
|
|
2281
|
-
type: Input
|
|
2282
|
-
}], popupSettings: [{
|
|
2283
|
-
type: Input
|
|
2284
|
-
}], checkableSettings: [{
|
|
2285
|
-
type: Input
|
|
2286
|
-
}], data: [{
|
|
2287
|
-
type: Input
|
|
2288
|
-
}], value: [{
|
|
2289
|
-
type: Input
|
|
2290
|
-
}], dataItems: [{
|
|
2291
|
-
type: Input
|
|
2292
|
-
}], textField: [{
|
|
2293
|
-
type: Input
|
|
2294
|
-
}], valueField: [{
|
|
2295
|
-
type: Input
|
|
2296
|
-
}], valueDepth: [{
|
|
2297
|
-
type: Input
|
|
2298
|
-
}], loading: [{
|
|
2299
|
-
type: Input
|
|
2300
|
-
}], placeholder: [{
|
|
2301
|
-
type: Input
|
|
2302
|
-
}], listHeight: [{
|
|
2303
|
-
type: Input
|
|
2304
|
-
}], disabled: [{
|
|
2305
|
-
type: Input
|
|
2306
|
-
}], readonly: [{
|
|
2307
|
-
type: Input
|
|
2308
|
-
}, {
|
|
2309
|
-
type: HostBinding,
|
|
2310
|
-
args: ['class.k-readonly']
|
|
2311
|
-
}], valuePrimitive: [{
|
|
2312
|
-
type: Input
|
|
2313
|
-
}], loadOnDemand: [{
|
|
2314
|
-
type: Input
|
|
2315
|
-
}], focusableId: [{
|
|
2316
|
-
type: Input
|
|
2317
|
-
}], clearButton: [{
|
|
2318
|
-
type: Input
|
|
2319
|
-
}], filterable: [{
|
|
2320
|
-
type: Input
|
|
2321
|
-
}], checkAll: [{
|
|
2322
|
-
type: Input
|
|
2323
|
-
}], hasChildren: [{
|
|
2324
|
-
type: Input
|
|
2325
|
-
}], fetchChildren: [{
|
|
2326
|
-
type: Input
|
|
2327
|
-
}], isNodeExpanded: [{
|
|
2328
|
-
type: Input
|
|
2329
|
-
}], isNodeVisible: [{
|
|
2330
|
-
type: Input
|
|
2331
|
-
}], itemDisabled: [{
|
|
2332
|
-
type: Input
|
|
2333
|
-
}], tagMapper: [{
|
|
2334
|
-
type: Input
|
|
2335
|
-
}], onFocus: [{
|
|
2336
|
-
type: Output,
|
|
2337
|
-
args: ['focus']
|
|
2338
|
-
}], onBlur: [{
|
|
2339
|
-
type: Output,
|
|
2340
|
-
args: ['blur']
|
|
2341
|
-
}], open: [{
|
|
2342
|
-
type: Output
|
|
2343
|
-
}], opened: [{
|
|
2344
|
-
type: Output
|
|
2345
|
-
}], close: [{
|
|
2346
|
-
type: Output
|
|
2347
|
-
}], closed: [{
|
|
2348
|
-
type: Output
|
|
2349
|
-
}], nodeExpand: [{
|
|
2350
|
-
type: Output
|
|
2351
|
-
}], nodeCollapse: [{
|
|
2352
|
-
type: Output
|
|
2353
|
-
}], valueChange: [{
|
|
2354
|
-
type: Output
|
|
2355
|
-
}], removeTag: [{
|
|
2356
|
-
type: Output
|
|
2357
|
-
}], filterChange: [{
|
|
2358
|
-
type: Output
|
|
2359
|
-
}] } });
|