@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.
Files changed (84) hide show
  1. package/common/localization/messages.d.ts +1 -1
  2. package/dropdowntrees/checked-state/base-check.directive.d.ts +1 -1
  3. package/fesm2022/progress-kendo-angular-dropdowns.mjs +173 -173
  4. package/package.json +14 -22
  5. package/schematics/ngAdd/index.js +2 -2
  6. package/esm2022/autocomplete/autocomplete.component.mjs +0 -1687
  7. package/esm2022/autocomplete/autocomplete.module.mjs +0 -70
  8. package/esm2022/comboboxes/combobox-column/column-cell-template.directive.mjs +0 -42
  9. package/esm2022/comboboxes/combobox-column/column-header-template.directive.mjs +0 -40
  10. package/esm2022/comboboxes/combobox-column/combobox-column.component.mjs +0 -116
  11. package/esm2022/comboboxes/combobox-column/util.mjs +0 -60
  12. package/esm2022/comboboxes/combobox.component.mjs +0 -2149
  13. package/esm2022/comboboxes/combobox.module.mjs +0 -77
  14. package/esm2022/comboboxes/multicolumncombobox.component.mjs +0 -883
  15. package/esm2022/common/adaptive-renderer.component.mjs +0 -253
  16. package/esm2022/common/constants/error-messages.mjs +0 -61
  17. package/esm2022/common/data.service.mjs +0 -250
  18. package/esm2022/common/disabled-items/disabled-items.service.mjs +0 -47
  19. package/esm2022/common/disabled-items/item-disabled.mjs +0 -5
  20. package/esm2022/common/filter-input.directive.mjs +0 -39
  21. package/esm2022/common/filtering/filter-settings.mjs +0 -5
  22. package/esm2022/common/filtering/filter.directive.mjs +0 -136
  23. package/esm2022/common/filtering/filterable-component.mjs +0 -34
  24. package/esm2022/common/list-item.directive.mjs +0 -25
  25. package/esm2022/common/list.component.mjs +0 -968
  26. package/esm2022/common/localization/custom-messages.component.mjs +0 -96
  27. package/esm2022/common/localization/localized-messages.directive.mjs +0 -47
  28. package/esm2022/common/localization/messages.mjs +0 -77
  29. package/esm2022/common/models/checkboxes-settings.mjs +0 -15
  30. package/esm2022/common/models/direction.mjs +0 -5
  31. package/esm2022/common/models/fillmode.mjs +0 -5
  32. package/esm2022/common/models/list-type.mjs +0 -5
  33. package/esm2022/common/models/page-change-event.mjs +0 -5
  34. package/esm2022/common/models/popup-settings.mjs +0 -5
  35. package/esm2022/common/models/preventable-event.mjs +0 -25
  36. package/esm2022/common/models/remove-tag-event.mjs +0 -23
  37. package/esm2022/common/models/rounded.mjs +0 -5
  38. package/esm2022/common/models/size.mjs +0 -5
  39. package/esm2022/common/models/virtualization-settings.mjs +0 -24
  40. package/esm2022/common/navigation/navigation-action.mjs +0 -32
  41. package/esm2022/common/navigation/navigation.service.mjs +0 -188
  42. package/esm2022/common/searchbar.component.mjs +0 -386
  43. package/esm2022/common/selection/selectable.directive.mjs +0 -83
  44. package/esm2022/common/selection/selection.service.mjs +0 -166
  45. package/esm2022/common/shared-events.directive.mjs +0 -99
  46. package/esm2022/common/taglist.component.mjs +0 -295
  47. package/esm2022/common/templates/custom-item-template.directive.mjs +0 -48
  48. package/esm2022/common/templates/fixed-group-template.directive.mjs +0 -55
  49. package/esm2022/common/templates/footer-template.directive.mjs +0 -49
  50. package/esm2022/common/templates/group-tag-template.directive.mjs +0 -47
  51. package/esm2022/common/templates/group-template.directive.mjs +0 -55
  52. package/esm2022/common/templates/header-template.directive.mjs +0 -49
  53. package/esm2022/common/templates/item-template.directive.mjs +0 -48
  54. package/esm2022/common/templates/no-data-template.directive.mjs +0 -49
  55. package/esm2022/common/templates/tag-template.directive.mjs +0 -46
  56. package/esm2022/common/templates/value-template.directive.mjs +0 -50
  57. package/esm2022/common/util.mjs +0 -376
  58. package/esm2022/directives.mjs +0 -172
  59. package/esm2022/dropdownlist/dropdownlist.component.mjs +0 -1999
  60. package/esm2022/dropdownlist/dropdownlist.module.mjs +0 -79
  61. package/esm2022/dropdowns.module.mjs +0 -76
  62. package/esm2022/dropdowntrees/checked-state/base-check.directive.mjs +0 -76
  63. package/esm2022/dropdowntrees/checked-state/check-all.directive.mjs +0 -170
  64. package/esm2022/dropdowntrees/checked-state/check.directive.mjs +0 -168
  65. package/esm2022/dropdowntrees/checked-state/checkable-settings.mjs +0 -5
  66. package/esm2022/dropdowntrees/checked-state/checked-item.mjs +0 -5
  67. package/esm2022/dropdowntrees/data-binding/dropdowntree/flat-binding.directive.mjs +0 -69
  68. package/esm2022/dropdowntrees/data-binding/dropdowntree/hierarchy-binding.directive.mjs +0 -62
  69. package/esm2022/dropdowntrees/data-binding/multiselecttree/flat-binding.directive.mjs +0 -69
  70. package/esm2022/dropdowntrees/data-binding/multiselecttree/hierarchy-binding.directive.mjs +0 -62
  71. package/esm2022/dropdowntrees/dropdowntree.component.mjs +0 -1967
  72. package/esm2022/dropdowntrees/dropdowntrees.module.mjs +0 -79
  73. package/esm2022/dropdowntrees/expanded-state/expand.directive.mjs +0 -49
  74. package/esm2022/dropdowntrees/lookup/lookup.mjs +0 -5
  75. package/esm2022/dropdowntrees/lookup/lookup.service.mjs +0 -82
  76. package/esm2022/dropdowntrees/multiselecttree.component.mjs +0 -2359
  77. package/esm2022/dropdowntrees/summary-tag/summary-tag.directive.mjs +0 -70
  78. package/esm2022/dropdowntrees/templates/node-template.directive.mjs +0 -31
  79. package/esm2022/index.mjs +0 -55
  80. package/esm2022/multiselect/multiselect.component.mjs +0 -2380
  81. package/esm2022/multiselect/multiselect.module.mjs +0 -79
  82. package/esm2022/multiselect/summary-tag.directive.mjs +0 -68
  83. package/esm2022/package-metadata.mjs +0 -16
  84. package/esm2022/progress-kendo-angular-dropdowns.mjs +0 -8
@@ -1,1999 +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 { Component, Renderer2, forwardRef, ElementRef, Input, Output, HostBinding, EventEmitter, ContentChild, ViewChild, ViewContainerRef, isDevMode, NgZone, TemplateRef, ChangeDetectorRef, HostListener, Injector } from '@angular/core';
6
- import { NG_VALUE_ACCESSOR, NgControl, ReactiveFormsModule, FormsModule } from '@angular/forms';
7
- import { validatePackage } from '@progress/kendo-licensing';
8
- import { packageMetadata } from '../package-metadata';
9
- import { merge, interval, Subscription } from 'rxjs';
10
- import { concatMap, filter, map, skipWhile, take, takeUntil, tap } from 'rxjs/operators';
11
- import { isDocumentAvailable, KendoInput, hasObservers, anyChanged, isChanged, EventsOutsideAngularDirective, ResizeSensorComponent, Keys, TemplateContextDirective, isSafari, guid, normalizeKeys, parseCSSClassNames } from '@progress/kendo-angular-common';
12
- import { AdaptiveService } from '@progress/kendo-angular-utils';
13
- import { isPresent, getter, shuffleData, sameCharsOnly, matchText, isUntouched, inDropDown, getSizeClass, getRoundedClass, getFillModeClass, isTruthy, setListBoxAriaLabelledBy, setActionSheetTitle, animationDuration } from '../common/util';
14
- import { SelectionService } from '../common/selection/selection.service';
15
- import { NavigationService, NavigationEvent } from '../common/navigation/navigation.service';
16
- import { ItemTemplateDirective } from '../common/templates/item-template.directive';
17
- import { GroupTemplateDirective } from '../common/templates/group-template.directive';
18
- import { FixedGroupTemplateDirective } from '../common/templates/fixed-group-template.directive';
19
- import { ValueTemplateDirective } from '../common/templates/value-template.directive';
20
- import { HeaderTemplateDirective } from '../common/templates/header-template.directive';
21
- import { FooterTemplateDirective } from '../common/templates/footer-template.directive';
22
- import { NoDataTemplateDirective } from '../common/templates/no-data-template.directive';
23
- import { NavigationAction } from '../common/navigation/navigation-action';
24
- import { PreventableEvent } from '../common/models/preventable-event';
25
- import { LocalizationService, L10N_PREFIX } from '@progress/kendo-angular-l10n';
26
- import { PopupService } from '@progress/kendo-angular-popup';
27
- import { DropDownListMessages } from '../common/constants/error-messages';
28
- import { DisabledItemsService } from '../common/disabled-items/disabled-items.service';
29
- import { DataService } from '../common/data.service';
30
- import { FilterableComponent } from '../common/filtering/filterable-component';
31
- import { ListComponent } from '../common/list.component';
32
- import { normalizeVirtualizationSettings } from '../common/models/virtualization-settings';
33
- import { caretAltDownIcon, searchIcon, xIcon } from '@progress/kendo-svg-icons';
34
- import { AdaptiveRendererComponent } from '../common/adaptive-renderer.component';
35
- import { FilterInputDirective } from '../common/filter-input.directive';
36
- import { NgClass, NgTemplateOutlet } from '@angular/common';
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-l10n";
42
- import * as i2 from "@progress/kendo-angular-popup";
43
- import * as i3 from "../common/selection/selection.service";
44
- import * as i4 from "../common/navigation/navigation.service";
45
- import * as i5 from "../common/disabled-items/disabled-items.service";
46
- import * as i6 from "../common/data.service";
47
- import * as i7 from "@progress/kendo-angular-utils";
48
- import * as i8 from "@angular/forms";
49
- /**
50
- * @hidden
51
- */
52
- export const DROPDOWNLIST_VALUE_ACCESSOR = {
53
- multi: true,
54
- provide: NG_VALUE_ACCESSOR,
55
- useExisting: forwardRef(() => DropDownListComponent)
56
- };
57
- const DEFAULT_SIZE = 'medium';
58
- const DEFAULT_ROUNDED = 'medium';
59
- const DEFAULT_FILL_MODE = 'solid';
60
- /**
61
- * Represents the Kendo UI for Angular [DropDownList]({% slug overview_ddl %}) component.
62
- *
63
- * @example
64
- * ```html
65
- * <kendo-dropdownlist [data]="["Item 1", "Item 2", "Item 3"]"></kendo-dropdownlist>
66
- * ```
67
- * @remarks
68
- * Supported children components are: {@link CustomMessagesComponent}.
69
- */
70
- export class DropDownListComponent {
71
- wrapper;
72
- localization;
73
- popupService;
74
- selectionService;
75
- navigationService;
76
- disabledItemsService;
77
- dataService;
78
- _zone;
79
- renderer;
80
- cdr;
81
- injector;
82
- adaptiveService;
83
- /**
84
- * @hidden
85
- */
86
- touchEnabled = touchEnabled;
87
- /**
88
- * @hidden
89
- */
90
- animationDuration = animationDuration;
91
- /**
92
- * @hidden
93
- */
94
- xIcon = xIcon;
95
- /**
96
- * @hidden
97
- */
98
- searchIcon = searchIcon;
99
- /**
100
- * @hidden
101
- */
102
- caretAltDownSVGIcon = caretAltDownIcon;
103
- /**
104
- * @hidden
105
- */
106
- customIconClass;
107
- /**
108
- * @hidden
109
- */
110
- adaptiveRenderer;
111
- /**
112
- * @hidden
113
- */
114
- searchInput;
115
- /**
116
- * @hidden
117
- */
118
- get actionSheet() {
119
- return this.adaptiveRenderer?.actionSheet;
120
- }
121
- /**
122
- * @hidden
123
- */
124
- get actionSheetSearchBar() {
125
- return this.adaptiveRenderer?.actionSheetSearchBar;
126
- }
127
- get width() {
128
- const wrapperWidth = isDocumentAvailable() ? this.wrapper.nativeElement.offsetWidth : 0;
129
- const width = this.popupSettings.width || wrapperWidth;
130
- const minWidth = isNaN(wrapperWidth) ? wrapperWidth : `${wrapperWidth}px`;
131
- const maxWidth = isNaN(width) ? width : `${width}px`;
132
- return { min: minWidth, max: maxWidth };
133
- }
134
- get height() {
135
- const popupHeight = this.popupSettings.height;
136
- return isPresent(popupHeight) ? `${popupHeight}px` : 'auto';
137
- }
138
- get widgetTabIndex() {
139
- if (this.disabled) {
140
- return undefined;
141
- }
142
- const providedTabIndex = Number(this.tabIndex);
143
- const defaultTabIndex = 0;
144
- return !isNaN(providedTabIndex) ? providedTabIndex : defaultTabIndex;
145
- }
146
- get ariaActivedescendant() {
147
- if (!isPresent(this.dataItem) || !this.isOpen) {
148
- return;
149
- }
150
- return this.optionPrefix + "-" + this.selectionService.focused;
151
- }
152
- get appendTo() {
153
- const { appendTo } = this.popupSettings;
154
- if (!appendTo || appendTo === 'root') {
155
- return undefined;
156
- }
157
- return appendTo === 'component' ? this.container : appendTo;
158
- }
159
- /**
160
- * @hidden
161
- */
162
- onFilterChange(text) {
163
- if (this.filterable) {
164
- this.filterChange.emit(text);
165
- }
166
- }
167
- /**
168
- * @hidden
169
- */
170
- get ariaLive() {
171
- return this.filterable ? 'polite' : 'off';
172
- }
173
- /**
174
- * Shows or hides the current group sticky header when using grouped data.
175
- * The sticky header displays by default. [see example.]({% slug grouping_autocomplete %}#toc-sticky-header)
176
- */
177
- showStickyHeader = true;
178
- /**
179
- * @hidden
180
- */
181
- icon;
182
- /**
183
- * @hidden
184
- */
185
- svgIcon;
186
- /**
187
- * Sets and gets the loading state of the `DropDownListComponent`.
188
- */
189
- loading;
190
- /**
191
- * Sets the data of the `DropDownListComponent`.
192
- *
193
- * The data must be an array-like list.
194
- */
195
- set data(data) {
196
- this.dataService.data = data || [];
197
- if (this.virtual) {
198
- this.virtual.skip = 0;
199
- }
200
- this.setState();
201
- }
202
- get data() {
203
- const virtual = this.virtual;
204
- if (virtual) {
205
- const start = virtual.skip || 0;
206
- const end = start + virtual.pageSize;
207
- // Use length instead of itemsCount because of the grouping.
208
- virtual.total = this.dataService.data.length;
209
- return this.dataService.data.slice(start, end);
210
- }
211
- return this.dataService.data;
212
- }
213
- /**
214
- * Sets the value of the `DropDownListComponent`.
215
- * The value can be a primitive (string, number) or a complex object.
216
- * Use the `valuePrimitive` option to define the type.
217
- *
218
- * All selected values not present in the source are ignored.
219
- */
220
- set value(newValue) {
221
- if (!isPresent(newValue)) {
222
- this._previousDataItem = undefined;
223
- }
224
- this._value = newValue;
225
- this.setState();
226
- this.cdr.markForCheck();
227
- }
228
- get value() {
229
- return this._value;
230
- }
231
- /**
232
- * Sets the data item field that represents the item text.
233
- * If the data contains only primitive values, do not define this property.
234
- *
235
- * The `textField` property can point to a nested property value, for example, `category.name`.
236
- */
237
- textField;
238
- /**
239
- * Sets the data item field that represents the item value.
240
- * If the data contains only primitive values, do not define this property.
241
- *
242
- * The `valueField` property can point to a nested property value, for example, `category.id`.
243
- */
244
- valueField;
245
- /**
246
- * Enables or disables the adaptive mode. The adaptive rendering is disabled by default.
247
- */
248
- adaptiveMode = 'none';
249
- /**
250
- * Sets the title of the ActionSheet rendered instead of the Popup on small screens.
251
- * By default, the ActionSheet title uses the label text of the `DropDownListComponent`.
252
- */
253
- adaptiveTitle = '';
254
- /**
255
- * Sets the subtitle of the ActionSheet rendered instead of the Popup on small screens.
256
- * By default, the ActionSheet does not render a subtitle.
257
- */
258
- adaptiveSubtitle = '';
259
- /**
260
- * @hidden
261
- */
262
- get isAdaptiveModeEnabled() {
263
- return this.adaptiveMode === 'auto';
264
- }
265
- /**
266
- * @hidden
267
- */
268
- windowSize = 'large';
269
- /**
270
- * @hidden
271
- */
272
- get isActionSheetExpanded() {
273
- return this.actionSheet?.expanded;
274
- }
275
- /**
276
- * @hidden
277
- */
278
- get isAdaptive() {
279
- return this.isAdaptiveModeEnabled && this.windowSize !== 'large';
280
- }
281
- /**
282
- * Configures the popup of the `DropDownListComponent`.
283
- *
284
- * The available options are:
285
- * - `animate: Boolean`&mdash;Controls the popup animation. The open and close animations are enabled by default.
286
- * - `width: Number | String`&mdash;Sets the width of the popup container. By default, the width of the host element is used. If set to `auto`, the component automatically adjusts the width of the popup and no item labels are wrapped. The `auto` mode is not supported when virtual scrolling is enabled.
287
- * - `height: Number`&mdash;Sets the height of the popup container.
288
- * - `popupClass: String`&mdash;Specifies a list of CSS classes used to style the popup.
289
- * - `appendTo: "root" | "component" | ViewContainerRef`&mdash;Specifies the component to which the popup will be appended.
290
- */
291
- set popupSettings(settings) {
292
- this._popupSettings = Object.assign({ animate: true }, settings);
293
- }
294
- get popupSettings() {
295
- return this._popupSettings;
296
- }
297
- /**
298
- * Sets the height of the options list in the popup.
299
- *
300
- * The `listHeight` property affects only the list of options, not the whole popup container.
301
- * To set the height of the popup container, use `popupSettings.height`.
302
- *
303
- * When using `adaptiveMode` and the screen size is `small` or `medium`, the `listHeight` property is set to null.
304
- *
305
- * @default 200
306
- */
307
- set listHeight(_listHeight) {
308
- this._listHeight = _listHeight;
309
- }
310
- get listHeight() {
311
- if (this.isAdaptive) {
312
- return;
313
- }
314
- return this._listHeight;
315
- }
316
- _listHeight = 200;
317
- /**
318
- * Sets the text of the default empty item. The value type must match the data type.
319
- */
320
- defaultItem;
321
- /**
322
- * Sets the disabled state of the component. To disable the component in reactive forms, see [Forms Support](slug:formssupport_ddl#toc-managing-the-dropdownlist-disabled-state-in-reactive-forms).
323
- */
324
- disabled;
325
- /**
326
- * Defines a Boolean function executed for each data item in the component. Determines whether the item is disabled. [See examples.]({% slug disableditems_ddl %})
327
- */
328
- set itemDisabled(fn) {
329
- if (typeof fn !== 'function') {
330
- throw new Error(`itemDisabled must be a function, but received ${JSON.stringify(fn)}.`);
331
- }
332
- this.disabledItemsService.itemDisabled = fn;
333
- }
334
- /**
335
- * Sets the read-only state of the component.
336
- *
337
- * @default false
338
- */
339
- readonly = false;
340
- /**
341
- * Enables the [filtering]({% slug filtering_ddl %}) functionality of the `DropDownListComponent`.
342
- */
343
- filterable = false;
344
- /**
345
- * Enables the [virtualization]({% slug virtualization_ddl %}) functionality.
346
- */
347
- set virtual(settings) {
348
- this._virtualSettings = normalizeVirtualizationSettings(settings);
349
- }
350
- get virtual() {
351
- return this._virtualSettings;
352
- }
353
- /**
354
- * Enables a case-insensitive search. Use this option when filtration is disabled.
355
- */
356
- ignoreCase = true;
357
- /**
358
- * Sets the delay before an item search is performed. Use this option when filtration is disabled.
359
- */
360
- delay = 500;
361
- /**
362
- * Specifies the type of the selected value. If set to `true`, the selected value must be a primitive value.
363
- * * [More information and example.]({% slug valuebinding_ddl %}#toc-primitive-values-from-object-fields)
364
- */
365
- set valuePrimitive(isPrimitive) {
366
- this._valuePrimitive = isPrimitive;
367
- }
368
- get valuePrimitive() {
369
- if (!isPresent(this._valuePrimitive)) {
370
- return !isPresent(this.valueField);
371
- }
372
- return this._valuePrimitive;
373
- }
374
- /**
375
- * Specifies the [`tabindex`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) of the component.
376
- */
377
- tabindex = 0;
378
- /**
379
- * @hidden
380
- */
381
- set tabIndex(tabIndex) {
382
- this.tabindex = tabIndex;
383
- }
384
- get tabIndex() {
385
- return this.tabindex;
386
- }
387
- /**
388
- * Sets the size of the component.
389
- *
390
- * The possible values are:
391
- * * `small`
392
- * * `medium` (default)
393
- * * `large`
394
- * * `none`
395
- *
396
- * @default 'medium'
397
- */
398
- set size(size) {
399
- const newSize = size ? size : DEFAULT_SIZE;
400
- this.renderer.removeClass(this.wrapper.nativeElement, getSizeClass('picker', this.size));
401
- if (size !== 'none') {
402
- this.renderer.addClass(this.wrapper.nativeElement, getSizeClass('picker', newSize));
403
- }
404
- this._size = newSize;
405
- }
406
- get size() {
407
- return this._size;
408
- }
409
- /**
410
- * Sets the border radius of the component.
411
- *
412
- * The possible values are:
413
- * * `small`
414
- * * `medium` (default)
415
- * * `large`
416
- * * `full`
417
- * * `none`
418
- *
419
- * @default 'medium'
420
- */
421
- set rounded(rounded) {
422
- const newRounded = rounded ? rounded : DEFAULT_ROUNDED;
423
- this.renderer.removeClass(this.wrapper.nativeElement, getRoundedClass(this.rounded));
424
- if (rounded !== 'none') {
425
- this.renderer.addClass(this.wrapper.nativeElement, getRoundedClass(newRounded));
426
- }
427
- this._rounded = rounded;
428
- }
429
- get rounded() {
430
- return this._rounded;
431
- }
432
- /**
433
- * Sets the fillMode of the component.
434
- *
435
- * The possible values are:
436
- * * `flat`
437
- * * `solid` (default)
438
- * * `outline`
439
- * * `none`
440
- *
441
- * @default 'solid'
442
- */
443
- set fillMode(fillMode) {
444
- const newFillMode = fillMode ? fillMode : DEFAULT_FILL_MODE;
445
- this.renderer.removeClass(this.wrapper.nativeElement, getFillModeClass('picker', this.fillMode));
446
- if (fillMode !== 'none') {
447
- this.renderer.addClass(this.wrapper.nativeElement, getFillModeClass('picker', newFillMode));
448
- }
449
- this._fillMode = newFillMode;
450
- }
451
- get fillMode() {
452
- return this._fillMode;
453
- }
454
- /**
455
- * Toggles the left and right arrow keys navigation functionality.
456
- * @hidden
457
- */
458
- leftRightArrowsNavigation = true;
459
- /**
460
- * Fires each time the value changes. [See example.](slug:events_ddl).
461
- */
462
- valueChange = new EventEmitter();
463
- /**
464
- ** Fires each time the user types in the input field. You can filter the source based on the filtration value. When the value is programmatically changed, the `valueChange` event is not triggered. [See example.](slug:events_ddl).
465
- */
466
- filterChange = new EventEmitter();
467
- /**
468
- * Fires each time the item selection changes. [see example.](slug:events_ddl).
469
- */
470
- selectionChange = new EventEmitter();
471
- /**
472
- * Fires each time the popup is about to open. This event is preventable. If you cancel it, the popup remains closed. [see example.]({% slug openstate_ddl %}#toc-preventing-opening-and-closing)
473
- */
474
- open = new EventEmitter();
475
- /**
476
- * Fires after the popup has been opened.
477
- */
478
- opened = new EventEmitter();
479
- /**
480
- * Fires each time the popup is about to close. This event is preventable. If you cancel it, the popup remains open. [see example.]({% slug openstate_ddl %}#toc-preventing-opening-and-closing)
481
- */
482
- close = new EventEmitter();
483
- /**
484
- * Fires after the popup has been closed.
485
- */
486
- closed = new EventEmitter();
487
- /**
488
- * Fires each time the user focuses the `DropDownListComponent`.
489
- */
490
- onFocus = new EventEmitter();
491
- /**
492
- * Fires each time the `DropDownListComponent` gets blurred.
493
- */
494
- onBlur = new EventEmitter();
495
- itemTemplate;
496
- groupTemplate;
497
- fixedGroupTemplate;
498
- valueTemplate;
499
- headerTemplate;
500
- footerTemplate;
501
- noDataTemplate;
502
- container;
503
- popupTemplate;
504
- optionsList;
505
- /**
506
- * @hidden
507
- */
508
- blurComponent(event) {
509
- if (event.target !== this.wrapper.nativeElement) {
510
- return;
511
- }
512
- event.stopImmediatePropagation();
513
- this.hostElementBlurred.emit();
514
- }
515
- /**
516
- * @hidden
517
- */
518
- blurFilterInput() {
519
- this.filterBlurred.emit();
520
- }
521
- /**
522
- * @hidden
523
- */
524
- focusComponent(event) {
525
- if (event.target !== this.wrapper.nativeElement) {
526
- return;
527
- }
528
- event.stopImmediatePropagation();
529
- this.hostElementFocused.emit();
530
- if (!this.isFocused) {
531
- this.isFocused = true;
532
- if (hasObservers(this.onFocus)) {
533
- this._zone.run(() => {
534
- this.onFocus.emit();
535
- });
536
- }
537
- }
538
- }
539
- /**
540
- * @hidden
541
- */
542
- onResize() {
543
- const currentWindowSize = this.adaptiveService.size;
544
- if (this.isAdaptiveModeEnabled && this.windowSize !== currentWindowSize) {
545
- if (this.isOpen) {
546
- this.togglePopup(false);
547
- }
548
- this.windowSize = currentWindowSize;
549
- }
550
- if (this.isOpen && !this.isActionSheetExpanded) {
551
- const popupWrapper = this.popupRef.popupElement;
552
- const { min, max } = this.width;
553
- popupWrapper.style.minWidth = min;
554
- popupWrapper.style.width = max;
555
- }
556
- }
557
- hostClasses = true;
558
- get isDisabledClass() {
559
- return this.disabled || null;
560
- }
561
- get isLoading() {
562
- return this.loading;
563
- }
564
- /**
565
- * @hidden
566
- */
567
- focusableId = `k-${guid()}`;
568
- get dir() {
569
- return this.direction;
570
- }
571
- get hostTabIndex() {
572
- return this.widgetTabIndex;
573
- }
574
- get readonlyClass() {
575
- return this.readonly;
576
- }
577
- get readonlyAttr() {
578
- return this.readonly ? '' : null;
579
- }
580
- get isBusy() {
581
- return this.isLoading;
582
- }
583
- role = 'combobox';
584
- haspopup = 'listbox';
585
- get hostAriaInvalid() {
586
- return this.formControl?.invalid ? true : null;
587
- }
588
- /**
589
- * @hidden
590
- */
591
- keydown(event, input) {
592
- if (input) {
593
- event.stopPropagation();
594
- }
595
- const firstIndex = isPresent(this.defaultItem) ? -1 : 0;
596
- const focused = isNaN(this.selectionService.focused) ? this.firstFocusableIndex(firstIndex) : this.selectionService.focused;
597
- let offset = 0;
598
- if (this.disabled || this.readonly) {
599
- return;
600
- }
601
- // on some keyboards, Home and End keys are mapped to Numpad keys
602
- const code = normalizeKeys(event);
603
- const isHomeKey = code === Keys.Home;
604
- const isEndKey = code === Keys.End;
605
- const isHomeEnd = isHomeKey || isEndKey;
606
- const isFilterFocused = this.filterable && this.isFocused && this.isOpen;
607
- if (isFilterFocused && isHomeEnd) {
608
- return;
609
- }
610
- const hasSelected = isPresent(this.selectionService.selected[0]);
611
- const focusedItemNotSelected = isPresent(this.selectionService.focused) && !this.selectionService.isSelected(this.selectionService.focused);
612
- if (!hasSelected || focusedItemNotSelected) {
613
- if (code === Keys.ArrowDown || code === Keys.ArrowRight && this.leftRightArrowsNavigation) {
614
- offset = -1;
615
- }
616
- else if (code === Keys.ArrowUp || code === Keys.ArrowLeft && this.leftRightArrowsNavigation) {
617
- offset = 1;
618
- }
619
- }
620
- const eventData = event;
621
- const action = this.navigationService.process({
622
- current: focused + offset,
623
- max: this.dataService.itemsCount - 1,
624
- min: this.defaultItem ? -1 : 0,
625
- originalEvent: eventData,
626
- openOnSpace: !this.isOpen,
627
- closeOnSpace: this.isOpen && !input && !(event.target instanceof HTMLInputElement)
628
- });
629
- const leftRightKeys = (action === NavigationAction.Left) || (action === NavigationAction.Right) && this.leftRightArrowsNavigation;
630
- if (action !== NavigationAction.Undefined &&
631
- action !== NavigationAction.Tab &&
632
- action !== NavigationAction.Backspace &&
633
- action !== NavigationAction.Delete &&
634
- action !== NavigationAction.PageDown &&
635
- action !== NavigationAction.PageUp &&
636
- action !== NavigationAction.SelectAll &&
637
- !(leftRightKeys && this.filterable) &&
638
- action !== NavigationAction.Enter //enter when popup is opened is handled before `handleEnter`
639
- ) {
640
- eventData.preventDefault();
641
- }
642
- if (action === NavigationAction.Tab && this.isActionSheetExpanded) {
643
- this.togglePopup(false);
644
- }
645
- }
646
- /**
647
- * @hidden
648
- */
649
- keypress(event) {
650
- if (this.disabled || this.readonly || this.filterable) {
651
- return;
652
- }
653
- this.onKeyPress(event);
654
- }
655
- /**
656
- * @hidden
657
- */
658
- click() {
659
- if (!this.isActionSheetExpanded) {
660
- this.focus();
661
- this.togglePopup(!this.isOpen);
662
- }
663
- }
664
- groupIndices = [];
665
- optionPrefix = `k-${guid()}`;
666
- valueLabelId;
667
- filterText = '';
668
- listBoxId = `k-${guid()}`;
669
- subs = new Subscription();
670
- _isFocused = false;
671
- set isFocused(isFocused) {
672
- this.renderer[isFocused ? 'addClass' : 'removeClass'](this.wrapper.nativeElement, 'k-focus');
673
- this._isFocused = isFocused;
674
- }
675
- get isFocused() {
676
- return this._isFocused;
677
- }
678
- direction;
679
- dataItem;
680
- popupRef;
681
- onTouchedCallback = (_) => { };
682
- onChangeCallback = (_) => { };
683
- popupMouseDownHandler;
684
- word = "";
685
- last = "";
686
- typingTimeout;
687
- filterFocused = new EventEmitter();
688
- filterBlurred = new EventEmitter();
689
- hostElementFocused = new EventEmitter();
690
- hostElementBlurred = new EventEmitter();
691
- touchstartDisposeHandler;
692
- _value;
693
- _open = false;
694
- _previousDataItem;
695
- _valuePrimitive;
696
- text;
697
- _popupSettings = { animate: true };
698
- _virtualSettings;
699
- _size = 'medium';
700
- _rounded = 'medium';
701
- _fillMode = 'solid';
702
- constructor(wrapper, localization, popupService, selectionService, navigationService, disabledItemsService, dataService, _zone, renderer, cdr, injector, adaptiveService) {
703
- this.wrapper = wrapper;
704
- this.localization = localization;
705
- this.popupService = popupService;
706
- this.selectionService = selectionService;
707
- this.navigationService = navigationService;
708
- this.disabledItemsService = disabledItemsService;
709
- this.dataService = dataService;
710
- this._zone = _zone;
711
- this.renderer = renderer;
712
- this.cdr = cdr;
713
- this.injector = injector;
714
- this.adaptiveService = adaptiveService;
715
- validatePackage(packageMetadata);
716
- this.direction = localization.rtl ? 'rtl' : 'ltr';
717
- this.data = [];
718
- this.subscribeEvents();
719
- this.subscribeTouchEvents();
720
- this.subscribeFocusEvents();
721
- this.popupMouseDownHandler = this.onMouseDown.bind(this);
722
- }
723
- ngOnInit() {
724
- this.renderer.removeAttribute(this.wrapper.nativeElement, "tabindex");
725
- this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-expanded', 'false');
726
- if (this.ariaActivedescendant) {
727
- this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-activedescendant', this.ariaActivedescendant);
728
- }
729
- this.subs.add(this.localization
730
- .changes.subscribe(({ rtl }) => {
731
- this.direction = rtl ? 'rtl' : 'ltr';
732
- this.cdr.detectChanges();
733
- }));
734
- this.assignAriaDescribedBy();
735
- this.setComponentClasses();
736
- }
737
- ngAfterViewInit() {
738
- this.windowSize = this.adaptiveService.size;
739
- }
740
- /**
741
- * @hidden
742
- * Used by the TextBoxContainer to determine if the component is empty.
743
- */
744
- isEmpty() {
745
- const value = this.value;
746
- return !(value === 0 || value === false || value || this.defaultItem);
747
- }
748
- /**
749
- * @hidden
750
- */
751
- onFilterFocus() {
752
- this.filterFocused.emit();
753
- }
754
- /**
755
- * @hidden
756
- */
757
- ngOnDestroy() {
758
- this.destroyPopup();
759
- this.subs.unsubscribe();
760
- this.unSubscribeFocusEvents();
761
- if (this.touchstartDisposeHandler) {
762
- this.touchstartDisposeHandler();
763
- }
764
- }
765
- /**
766
- * @hidden
767
- */
768
- ngOnChanges(changes) {
769
- const virtual = this.virtual;
770
- const requestInitialData = virtual && changes['data'] && changes['data'].isFirstChange();
771
- if (requestInitialData) {
772
- this.pageChange({ skip: 0, take: virtual.pageSize });
773
- }
774
- if (isChanged('defaultItem', changes, false)) {
775
- this.disabledItemsService.defaultItem = this.defaultItem;
776
- }
777
- if (anyChanged(['textField', 'valueField', 'valuePrimitive', 'defaultItem', 'itemDisabled'], changes, false)) {
778
- this.setState();
779
- }
780
- }
781
- /**
782
- * @hidden
783
- */
784
- ngAfterContentChecked() {
785
- this.verifySettings();
786
- }
787
- /**
788
- * @hidden
789
- */
790
- get formControl() {
791
- const ngControl = this.injector.get(NgControl, null);
792
- return ngControl?.control || null;
793
- }
794
- /**
795
- * Focuses a specific item of the `DropDownListComponent` based on the provided index. If there is a default item, it is positioned at index `-1`. If `null` or an invalid index is provided, the focus is removed.
796
- */
797
- focusItemAt(index) {
798
- const minIndex = isPresent(this.defaultItem) ? -1 : 0;
799
- const isInRange = minIndex <= index && index < this.data.length;
800
- if (isPresent(index) && isInRange && !this.disabledItemsService.isIndexDisabled(index)) {
801
- this.selectionService.focus(index);
802
- }
803
- else {
804
- this.selectionService.focus(null);
805
- }
806
- }
807
- /**
808
- * Focuses the `DropDownListComponent`.
809
- */
810
- focus() {
811
- if (!this.disabled) {
812
- this.wrapper.nativeElement.focus();
813
- }
814
- }
815
- /**
816
- * Blurs the `DropDownListComponent`.
817
- */
818
- blur() {
819
- if (!this.disabled) {
820
- this.wrapper.nativeElement.blur();
821
- this.cdr.detectChanges();
822
- }
823
- }
824
- /**
825
- * Toggles the visibility of the Popup or ActionSheet. If you use the `toggle` method to open or close the Popup, the `open` and `close` events are not fired.
826
- *
827
- * @param open - The state of the popup.
828
- */
829
- toggle(open) {
830
- // The Promise is required to open the popup on load.
831
- // Otherwise, the "Expression has changed..." type error will be thrown.
832
- Promise.resolve(null).then(() => {
833
- const shouldOpen = isPresent(open) ? open : !this._open;
834
- this._toggle(shouldOpen);
835
- });
836
- }
837
- _toggle(open) {
838
- this._open = open;
839
- this.destroyPopup();
840
- if (this.isActionSheetExpanded) {
841
- this.closeActionSheet();
842
- }
843
- if (this._open) {
844
- this.createPopup();
845
- }
846
- }
847
- triggerPopupEvents(open) {
848
- const eventArgs = new PreventableEvent();
849
- if (open) {
850
- this.open.emit(eventArgs);
851
- }
852
- else {
853
- this.close.emit(eventArgs);
854
- }
855
- return eventArgs.isDefaultPrevented();
856
- }
857
- /**
858
- * @hidden
859
- */
860
- togglePopup(open) {
861
- const isDisabled = this.disabled || this.readonly;
862
- const sameState = this.isOpen === open;
863
- if (isDisabled || sameState) {
864
- return;
865
- }
866
- const isDefaultPrevented = this.triggerPopupEvents(open);
867
- if (!isDefaultPrevented) {
868
- if (!open && this.filterable && this.isFocused) {
869
- this.focus();
870
- }
871
- this._toggle(open);
872
- }
873
- }
874
- /**
875
- * Returns the current open state. Returns `true` if the popup or actionSheet is open.
876
- */
877
- get isOpen() {
878
- return isTruthy(this._open || this.isActionSheetExpanded);
879
- }
880
- /**
881
- * Resets the value of the `DropDownListComponent`. If you use the `reset` method to clear the value, the model does not update automatically and the `selectionChange` and `valueChange` events are not fired.
882
- */
883
- reset() {
884
- this.value = undefined;
885
- }
886
- /**
887
- * @hidden
888
- */
889
- messageFor(key) {
890
- return this.localization.get(key);
891
- }
892
- /**
893
- * @hidden
894
- */
895
- writeValue(value) {
896
- this.value = value === null ? undefined : value;
897
- }
898
- /**
899
- * @hidden
900
- */
901
- registerOnChange(fn) {
902
- this.onChangeCallback = fn;
903
- }
904
- /**
905
- * @hidden
906
- */
907
- registerOnTouched(fn) {
908
- this.onTouchedCallback = fn;
909
- }
910
- /**
911
- * @hidden
912
- */
913
- setDisabledState(isDisabled) {
914
- this.cdr.markForCheck();
915
- this.disabled = isDisabled;
916
- }
917
- /**
918
- * @hidden
919
- */
920
- get selectButtonClasses() {
921
- return `${this.size ? getSizeClass('button', this.size) : ''} ${this.fillMode ? 'k-button-' + this.fillMode : ''} ${this.fillMode ? 'k-button-' + this.fillMode + '-base' : ''}`;
922
- }
923
- /**
924
- * @hidden
925
- */
926
- get filterInputClasses() {
927
- return `${this.size ? getSizeClass('input', this.size) : ''} ${this.fillMode ? 'k-input-' + this.fillMode : ''} ${this.rounded ? getRoundedClass(this.rounded) : ''}`;
928
- }
929
- /**
930
- * @hidden
931
- */
932
- get listContainerClasses() {
933
- const containerClasses = ['k-list-container', 'k-dropdownlist-popup'];
934
- if (!this.popupSettings.popupClass) {
935
- return containerClasses;
936
- }
937
- const parsedPopupClasses = parseCSSClassNames(this.popupSettings.popupClass);
938
- if (parsedPopupClasses?.length) {
939
- containerClasses.push(...parsedPopupClasses);
940
- }
941
- return containerClasses;
942
- }
943
- /**
944
- * @hidden
945
- */
946
- getText() {
947
- return this.text;
948
- }
949
- createPopup() {
950
- if (this.virtual) {
951
- this.virtual.skip = 0;
952
- }
953
- this.windowSize = this.adaptiveService.size;
954
- if (this.isAdaptive) {
955
- this.openActionSheet();
956
- return;
957
- }
958
- const horizontalAlign = this.direction === "rtl" ? "right" : "left";
959
- const anchorPosition = { horizontal: horizontalAlign, vertical: "bottom" };
960
- const popupPosition = { horizontal: horizontalAlign, vertical: "top" };
961
- const appendToComponent = typeof this.popupSettings.appendTo === 'string' && this.popupSettings.appendTo === 'component';
962
- this.popupRef = this.popupService.open({
963
- anchor: this.wrapper,
964
- anchorAlign: anchorPosition,
965
- animate: this.popupSettings.animate,
966
- appendTo: this.appendTo,
967
- content: this.popupTemplate,
968
- popupAlign: popupPosition,
969
- popupClass: this.listContainerClasses,
970
- positionMode: appendToComponent ? 'fixed' : 'absolute'
971
- });
972
- this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-expanded', 'true');
973
- this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-controls', this.listBoxId);
974
- const popupWrapper = this.popupRef.popupElement;
975
- const { min, max } = this.width;
976
- popupWrapper.addEventListener('mousedown', this.popupMouseDownHandler);
977
- popupWrapper.style.minWidth = min;
978
- popupWrapper.style.width = max;
979
- popupWrapper.style.height = this.height;
980
- popupWrapper.setAttribute('dir', this.direction);
981
- if (!this.appendTo) {
982
- this.renderer.setAttribute(popupWrapper, 'role', 'region');
983
- this.renderer.setAttribute(popupWrapper, 'aria-label', this.messageFor('popupLabel'));
984
- }
985
- this.subs.add(this.popupRef.popupOpen.subscribe(() => {
986
- this.cdr.detectChanges();
987
- if (!this.dataService.grouped) {
988
- setListBoxAriaLabelledBy(this.optionsList, this.wrapper, this.renderer);
989
- }
990
- this.setAriaactivedescendant();
991
- this.optionsList.scrollToItem(this.selectionService.focused);
992
- this.selectionService.focus(this.selectionService.focused);
993
- this.opened.emit();
994
- }));
995
- this.subs.add(this.popupRef.popupClose.subscribe(() => {
996
- this.closed.emit();
997
- }));
998
- if (!this.filterable) {
999
- this.subs.add(this.popupRef.popupAnchorViewportLeave.subscribe(() => this.togglePopup(false)));
1000
- }
1001
- }
1002
- destroyPopup() {
1003
- if (this.popupRef) {
1004
- this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-expanded', 'false');
1005
- this.renderer.removeAttribute(this.wrapper.nativeElement, 'aria-controls');
1006
- this.renderer.removeAttribute(this.wrapper.nativeElement, 'aria-activedescendant');
1007
- this.popupRef.popupElement
1008
- .removeEventListener('mousedown', this.popupMouseDownHandler);
1009
- this.popupRef.close();
1010
- this.popupRef = null;
1011
- }
1012
- }
1013
- updateState({ dataItem, confirm = false }) {
1014
- this.dataItem = dataItem;
1015
- this.text = getter(dataItem, this.textField);
1016
- if (confirm) {
1017
- this._previousDataItem = dataItem;
1018
- }
1019
- }
1020
- clearState() {
1021
- this.text = undefined;
1022
- this.dataItem = undefined;
1023
- }
1024
- resetSelection(index) {
1025
- const clear = !isPresent(index);
1026
- this.selectionService.resetSelection(clear ? [] : [index]);
1027
- this.selectionService.focused = clear ? this.firstFocusableIndex(0) : index;
1028
- }
1029
- onSelectionChange({ dataItem }) {
1030
- this.updateState({ dataItem });
1031
- this.selectionChange.emit(dataItem);
1032
- // reassigning the value label ID as aria-deascibedby forces firefox/nvda, forefox/jaws to read
1033
- // the new value when the popup is closed and the value is changed with the arrow keys (up/down)
1034
- this.assignAriaDescribedBy();
1035
- this.setAriaactivedescendant();
1036
- }
1037
- subscribeEvents() {
1038
- if (!isDocumentAvailable()) {
1039
- return;
1040
- }
1041
- // Item selection when the popup is open.
1042
- this.subs.add(this.selectionService.onSelect.pipe(filter(() => this.isOpen), map(this.itemFromEvent.bind(this)))
1043
- .subscribe(this.onSelectionChange.bind(this)));
1044
- // Item selection when the popup is closed | clicked | enter, and so on.
1045
- this.subs.add(merge(this.selectionService.onSelect.pipe(filter(() => !this.isOpen)), this.selectionService.onChange).pipe(map(this.itemFromEvent.bind(this)), tap(() => this.togglePopup(false)))
1046
- .subscribe(({ dataItem, value: newValue, newSelection }) => {
1047
- if (newSelection) {
1048
- this.onSelectionChange({ dataItem });
1049
- }
1050
- const shouldUsePrevious = !isPresent(dataItem) && this._previousDataItem;
1051
- const shouldUseNewValue = newValue !== getter(this.value, this.valueField);
1052
- if (shouldUsePrevious) {
1053
- this.updateState({ dataItem: this._previousDataItem });
1054
- this.resetSelection();
1055
- }
1056
- else if (shouldUseNewValue) {
1057
- this.value = this.valuePrimitive ? newValue : dataItem;
1058
- this._previousDataItem = dataItem;
1059
- this.emitChange(this.value);
1060
- }
1061
- this.clearFilter();
1062
- }));
1063
- this.subs.add(merge(this.navigationService.up, this.navigationService.down, this.navigationService.left.pipe(filter(() => this.leftRightArrowsNavigation), skipWhile(() => this.filterable)), this.navigationService.right.pipe(filter(() => this.leftRightArrowsNavigation), skipWhile(() => this.filterable)), this.navigationService.home, this.navigationService.end)
1064
- .pipe(filter((event) => !isNaN(event.index)))
1065
- .subscribe((event) => this.selectionService.select(event.index)));
1066
- this.subs.add(merge(this.navigationService.pagedown, this.navigationService.pageup).subscribe((event) => {
1067
- if (this.isOpen) {
1068
- event.originalEvent.preventDefault();
1069
- const code = normalizeKeys(event.originalEvent);
1070
- this.optionsList.scrollWithOnePage(NavigationAction[code]);
1071
- }
1072
- }));
1073
- this.subs.add(this.navigationService.open.subscribe(() => this.togglePopup(true)));
1074
- this.subs.add(this.navigationService.close.subscribe(() => {
1075
- this.togglePopup(false);
1076
- this.focus();
1077
- }));
1078
- this.subs.add(this.navigationService.enter
1079
- .pipe(tap((event) => event.originalEvent.preventDefault()))
1080
- .subscribe(this.handleEnter.bind(this)));
1081
- this.subs.add(this.navigationService.esc
1082
- .subscribe(this.handleEscape.bind(this)));
1083
- this.subs.add(this.filterBlurred.pipe(concatMap(() => interval(10).pipe(take(1), takeUntil(this.hostElementFocused))))
1084
- .subscribe(() => {
1085
- this.hostElementBlurred.emit();
1086
- }));
1087
- this._zone.runOutsideAngular(() => {
1088
- this.subs.add(merge(this.hostElementBlurred.pipe(concatMap(() => interval(10).pipe(take(1), takeUntil(this.filterFocused)))), this.navigationService.tab).pipe(tap(event => event instanceof NavigationEvent && this.focus()), filter(() => this.isFocused), filter(() => {
1089
- const isBrowserSafari = isDocumentAvailable() && isSafari(navigator.userAgent);
1090
- if (!isBrowserSafari) {
1091
- return true;
1092
- }
1093
- const hasFocusedKendoButton = this.popupRef?.popupElement.querySelector('.k-button.k-focus');
1094
- const shouldNotBlur = this.searchInput && hasFocusedKendoButton && hasObservers(this.filterChange);
1095
- if (shouldNotBlur) {
1096
- this.searchInput.nativeElement.focus();
1097
- this.isFocused = true;
1098
- }
1099
- return !shouldNotBlur;
1100
- }))
1101
- .subscribe(() => this.componentBlur()));
1102
- });
1103
- }
1104
- setAriaactivedescendant() {
1105
- if (this.ariaActivedescendant) {
1106
- this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-activedescendant', this.ariaActivedescendant);
1107
- if (this.searchInput) {
1108
- this.renderer.setAttribute(this.searchInput.nativeElement, 'aria-activedescendant', this.ariaActivedescendant);
1109
- }
1110
- }
1111
- }
1112
- subscribeTouchEvents() {
1113
- if (!isDocumentAvailable() || !this.touchEnabled) {
1114
- return;
1115
- }
1116
- this._zone.runOutsideAngular(() =>
1117
- // Roll up DropDownList on iOS when tapped outside
1118
- this.touchstartDisposeHandler = this.renderer.listen(document, 'touchstart', (e) => {
1119
- const target = e.target;
1120
- if (this.isFocused && !inDropDown(this.wrapper, target, this.popupRef)) {
1121
- this._zone.run(() => {
1122
- if (this.filterFocused) {
1123
- // Close popup if filter is focused
1124
- this.togglePopup(false);
1125
- }
1126
- this.blur();
1127
- });
1128
- }
1129
- }));
1130
- }
1131
- subscribeFocusEvents() {
1132
- if (isDocumentAvailable()) {
1133
- this.focusComponent = this.focusComponent.bind(this);
1134
- this.blurComponent = this.blurComponent.bind(this);
1135
- this._zone.runOutsideAngular(() => {
1136
- const useCapture = true;
1137
- document.addEventListener('focus', this.focusComponent, useCapture);
1138
- document.addEventListener('blur', this.blurComponent, useCapture);
1139
- });
1140
- }
1141
- }
1142
- unSubscribeFocusEvents() {
1143
- if (isDocumentAvailable()) {
1144
- const useCapture = true;
1145
- document.removeEventListener('focus', this.focusComponent, useCapture);
1146
- document.removeEventListener('blur', this.blurComponent, useCapture);
1147
- }
1148
- }
1149
- itemFromEvent(event) {
1150
- const index = event.indices[0];
1151
- let dataItem = this.dataService.itemAt(index);
1152
- dataItem = isPresent(dataItem) ? dataItem : this.currentOrDefault(index);
1153
- const value = getter(dataItem, this.valueField);
1154
- const newSelection = event.newSelection;
1155
- return {
1156
- dataItem,
1157
- index,
1158
- newSelection,
1159
- value
1160
- };
1161
- }
1162
- currentOrDefault(selectedIndex) {
1163
- const defaultItemIndex = -1;
1164
- if (isPresent(this.dataItem) && selectedIndex !== defaultItemIndex) {
1165
- return this.dataItem;
1166
- }
1167
- else {
1168
- return this.defaultItem;
1169
- }
1170
- }
1171
- firstFocusableIndex(index) {
1172
- const maxIndex = this.dataService.itemsCount - 1;
1173
- if (this.disabledItemsService.isIndexDisabled(index)) {
1174
- return (index < maxIndex) ? this.firstFocusableIndex(index + 1) : undefined;
1175
- }
1176
- else {
1177
- return index;
1178
- }
1179
- }
1180
- handleEnter() {
1181
- if (this.isOpen) {
1182
- this.selectionService.change(this.selectionService.focused);
1183
- this.focus();
1184
- }
1185
- else {
1186
- this.togglePopup(true);
1187
- }
1188
- }
1189
- handleEscape() {
1190
- if (isPresent(this.selectionService.selected[0])) {
1191
- this.selectionService.change(this.selectionService.selected[0]);
1192
- }
1193
- else {
1194
- this.togglePopup(false);
1195
- this.clearFilter();
1196
- }
1197
- this.focus();
1198
- }
1199
- clearFilter() {
1200
- if (!(this.filterable && this.filterText)) {
1201
- return;
1202
- }
1203
- this.filterText = "";
1204
- this.cdr.markForCheck();
1205
- this.filterChange.emit(this.filterText);
1206
- }
1207
- verifySettings() {
1208
- if (!isDevMode()) {
1209
- return;
1210
- }
1211
- if (this.defaultItem && this.valueField && typeof this.defaultItem !== "object") {
1212
- throw new Error(DropDownListMessages.defaultItem);
1213
- }
1214
- if (this.valuePrimitive === true && isPresent(this.value) && typeof this.value === "object") {
1215
- throw new Error(DropDownListMessages.primitive);
1216
- }
1217
- if (this.valuePrimitive === false && isPresent(this.value) && typeof this.value !== "object") {
1218
- throw new Error(DropDownListMessages.object);
1219
- }
1220
- const valueOrText = !isPresent(this.valueField) !== !isPresent(this.textField);
1221
- if (valueOrText) {
1222
- throw new Error(DropDownListMessages.textAndValue);
1223
- }
1224
- }
1225
- componentBlur() {
1226
- if (!this.isActionSheetExpanded) {
1227
- this.isFocused = false;
1228
- const selectionPresent = isPresent(this.selectionService.selected[0]);
1229
- const valueHasChanged = selectionPresent && getter(this.value, this.valueField) !== getter(this.dataService.itemAt(this.selectionService.selected[0]), this.valueField);
1230
- if (valueHasChanged ||
1231
- hasObservers(this.close) ||
1232
- hasObservers(this.onBlur) ||
1233
- hasObservers(this.filterChange) ||
1234
- isUntouched(this.wrapper.nativeElement) ||
1235
- this.formControl?.updateOn === 'blur') {
1236
- this._zone.run(() => {
1237
- if (valueHasChanged) {
1238
- this.selectionService.change(this.selectionService.selected[0]);
1239
- }
1240
- this.togglePopup(false);
1241
- this.clearFilter();
1242
- this.onBlur.emit();
1243
- this.onTouchedCallback();
1244
- });
1245
- }
1246
- else {
1247
- this.togglePopup(false);
1248
- //this is needed for Ang 18 not to throw ng0100 error when closing the popup
1249
- //the component could be refactored using kendoDropDownSharedEvents directive
1250
- //once we are able to debug against Angular 18
1251
- this.cdr.markForCheck();
1252
- }
1253
- }
1254
- }
1255
- /**
1256
- * @hidden
1257
- */
1258
- onMouseDown(event) {
1259
- const tagName = event.target.tagName.toLowerCase();
1260
- if (tagName !== "input") {
1261
- event.preventDefault();
1262
- }
1263
- }
1264
- onKeyPress(event) {
1265
- if (event.which === 0 || event.code === Keys.Enter || event.code === Keys.NumpadEnter || event.key.length > 1) {
1266
- return;
1267
- }
1268
- let character = event.key;
1269
- if (this.ignoreCase) {
1270
- character = character.toLowerCase();
1271
- }
1272
- if (character === " ") {
1273
- event.preventDefault();
1274
- }
1275
- this.word += character;
1276
- this.last = character;
1277
- this.search();
1278
- }
1279
- search() {
1280
- clearTimeout(this.typingTimeout);
1281
- if (!this.filterable) {
1282
- this.typingTimeout = setTimeout(() => {
1283
- this.word = "";
1284
- }, this.delay);
1285
- this.selectNext();
1286
- }
1287
- }
1288
- selectNext() {
1289
- let data = this.dataService
1290
- .filter((item) => isPresent(item) && !item.header && !this.disabledItemsService.isItemDisabled(item))
1291
- .map((item) => {
1292
- if (this.dataService.grouped) {
1293
- return { item: item.value, itemIndex: item.offsetIndex };
1294
- }
1295
- return { item: item, itemIndex: this.dataService.indexOf(item) };
1296
- });
1297
- const isInLoop = sameCharsOnly(this.word, this.last);
1298
- let dataLength = data.length;
1299
- const hasSelected = !isNaN(this.selectionService.selected[0]);
1300
- let startIndex = !hasSelected ? 0 : this.selectionService.selected[0];
1301
- let text, index, defaultItem;
1302
- if (this.defaultItem && !this.disabledItemsService.isItemDisabled(this.defaultItem)) {
1303
- defaultItem = { item: this.defaultItem, itemIndex: -1 };
1304
- dataLength += 1;
1305
- startIndex += 1;
1306
- }
1307
- startIndex += isInLoop && hasSelected ? 1 : 0;
1308
- data = shuffleData(data, startIndex, defaultItem);
1309
- index = 0;
1310
- for (; index < dataLength; index++) {
1311
- text = getter(data[index].item, this.textField);
1312
- const loopMatch = Boolean(isInLoop && matchText(text, this.last, this.ignoreCase));
1313
- const nextMatch = Boolean(matchText(text, this.word, this.ignoreCase));
1314
- if (loopMatch || nextMatch) {
1315
- index = data[index].itemIndex;
1316
- break;
1317
- }
1318
- }
1319
- if (index !== dataLength) {
1320
- this.navigate(index);
1321
- }
1322
- }
1323
- emitChange(value) {
1324
- this.onChangeCallback(value);
1325
- this.valueChange.emit(value);
1326
- }
1327
- navigate(index) {
1328
- this.selectionService.select(index);
1329
- }
1330
- findDataItem({ valueField, value }) {
1331
- const result = {
1332
- dataItem: null,
1333
- index: -1
1334
- };
1335
- const prop = dataItem => getter(dataItem, valueField);
1336
- let comparer;
1337
- if (this.dataService.grouped) {
1338
- comparer = (element) => {
1339
- return prop(element.value) === prop(value);
1340
- };
1341
- }
1342
- else {
1343
- comparer = (element) => {
1344
- return prop(element) === prop(value);
1345
- };
1346
- }
1347
- const index = this.dataService.findIndex(comparer);
1348
- result.dataItem = this.dataService.itemAt(index);
1349
- result.index = index;
1350
- return result;
1351
- }
1352
- setState() {
1353
- const value = this.value;
1354
- const valueField = this.valueField;
1355
- const textField = this.textField;
1356
- const primitive = this.valuePrimitive;
1357
- if (this.defaultItem) {
1358
- const defaultValue = getter(this.defaultItem, valueField);
1359
- const currentValue = getter(value, valueField);
1360
- if (!isPresent(value) || (currentValue === defaultValue)) {
1361
- this.updateState({ dataItem: this.defaultItem, confirm: true });
1362
- this.resetSelection(-1);
1363
- if (this.filterable && this.filterText && this.dataService.itemsCount) {
1364
- this.selectionService.focused = this.firstFocusableIndex(0);
1365
- }
1366
- return;
1367
- }
1368
- }
1369
- const resolved = this.findDataItem({ valueField, value });
1370
- // The data and value are of same shape,
1371
- // for example, value: 'foo', data: ['foo', 'bar']
1372
- // or value: { value: 1, text: 'foo' }, data: [{ value: 1, text: 'foo' }].
1373
- const ofSameType = !(primitive && textField);
1374
- if (resolved.dataItem) {
1375
- this.updateState({ dataItem: resolved.dataItem, confirm: true });
1376
- this.resetSelection(resolved.index);
1377
- }
1378
- else if (isPresent(value) && ofSameType) {
1379
- this.updateState({ dataItem: value });
1380
- this.resetSelection();
1381
- }
1382
- else if (this._previousDataItem) {
1383
- this.updateState({ dataItem: this._previousDataItem });
1384
- this.resetSelection();
1385
- }
1386
- else {
1387
- this.clearState();
1388
- this.resetSelection();
1389
- }
1390
- }
1391
- /**
1392
- * @hidden
1393
- */
1394
- handleFilter(event) {
1395
- this.filterChange.emit(event.target.value);
1396
- }
1397
- /**
1398
- * @hidden
1399
- */
1400
- handleClick() {
1401
- this.windowSize = this.adaptiveService.size;
1402
- if (this.isAdaptive) {
1403
- this.togglePopup(true);
1404
- }
1405
- }
1406
- /**
1407
- * @hidden
1408
- */
1409
- pageChange(event) {
1410
- const virtual = this.virtual;
1411
- virtual.skip = event.skip;
1412
- }
1413
- assignAriaDescribedBy() {
1414
- const currentValue = this.wrapper.nativeElement.getAttribute('aria-describedby') || '';
1415
- const trimmed = currentValue.replace(this.valueLabelId, '').trim();
1416
- // reset the value label ID to force readers to read the new value
1417
- this.valueLabelId = `k-${guid()}`;
1418
- // add to the current value - don't replace it
1419
- const newValue = `${this.valueLabelId} ${trimmed}`.trim();
1420
- this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-describedby', newValue);
1421
- }
1422
- setComponentClasses() {
1423
- if (this.size !== 'none') {
1424
- this.renderer.addClass(this.wrapper.nativeElement, getSizeClass('picker', this.size));
1425
- }
1426
- if (this.rounded !== 'none') {
1427
- this.renderer.addClass(this.wrapper.nativeElement, getRoundedClass(this.rounded));
1428
- }
1429
- if (this.fillMode !== 'none') {
1430
- this.renderer.addClass(this.wrapper.nativeElement, getFillModeClass('picker', this.fillMode));
1431
- }
1432
- }
1433
- closeActionSheet() {
1434
- this.actionSheet.toggle(false);
1435
- this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-expanded', 'false');
1436
- this.renderer.removeAttribute(this.wrapper.nativeElement, 'aria-controls');
1437
- if (this.filterable) {
1438
- this.adaptiveRenderer.searchBarValue = '';
1439
- this.filterChange.emit('');
1440
- }
1441
- this.closed.emit();
1442
- }
1443
- openActionSheet() {
1444
- this.actionSheet.toggle(true);
1445
- this.cdr.detectChanges();
1446
- this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-expanded', 'true');
1447
- this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-controls', this.listBoxId);
1448
- if (!this.dataService.grouped) {
1449
- setListBoxAriaLabelledBy(this.optionsList, this.wrapper, this.renderer);
1450
- }
1451
- this.setAriaactivedescendant();
1452
- this.adaptiveTitle = setActionSheetTitle(this.wrapper, this.adaptiveTitle);
1453
- this.cdr.detectChanges();
1454
- this.optionsList.scrollToItem(this.selectionService.focused);
1455
- this.selectionService.focus(this.selectionService.focused);
1456
- this.opened.emit();
1457
- }
1458
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DropDownListComponent, deps: [{ token: i0.ElementRef }, { token: i1.LocalizationService }, { token: i2.PopupService }, { token: i3.SelectionService }, { token: i4.NavigationService }, { token: i5.DisabledItemsService }, { token: i6.DataService }, { token: i0.NgZone }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: i0.Injector }, { token: i7.AdaptiveService }], target: i0.ɵɵFactoryTarget.Component });
1459
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: DropDownListComponent, isStandalone: true, selector: "kendo-dropdownlist", inputs: { customIconClass: "customIconClass", showStickyHeader: "showStickyHeader", icon: "icon", svgIcon: "svgIcon", loading: "loading", data: "data", value: "value", textField: "textField", valueField: "valueField", adaptiveMode: "adaptiveMode", adaptiveTitle: "adaptiveTitle", adaptiveSubtitle: "adaptiveSubtitle", popupSettings: "popupSettings", listHeight: "listHeight", defaultItem: "defaultItem", disabled: "disabled", itemDisabled: "itemDisabled", readonly: "readonly", filterable: "filterable", virtual: "virtual", ignoreCase: "ignoreCase", delay: "delay", valuePrimitive: "valuePrimitive", tabindex: "tabindex", tabIndex: "tabIndex", size: "size", rounded: "rounded", fillMode: "fillMode", leftRightArrowsNavigation: "leftRightArrowsNavigation", focusableId: ["id", "focusableId"] }, outputs: { valueChange: "valueChange", filterChange: "filterChange", selectionChange: "selectionChange", open: "open", opened: "opened", close: "close", closed: "closed", onFocus: "focus", onBlur: "blur" }, host: { listeners: { "keydown": "keydown($event)", "keypress": "keypress($event)", "click": "click()" }, properties: { "class.k-readonly": "this.readonly", "class.k-dropdownlist": "this.hostClasses", "class.k-picker": "this.hostClasses", "class.k-disabled": "this.isDisabledClass", "attr.aria-disabled": "this.isDisabledClass", "class.k-loading": "this.isLoading", "attr.id": "this.focusableId", "attr.dir": "this.dir", "attr.tabindex": "this.hostTabIndex", "attr.readonly": "this.readonlyAttr", "attr.aria-busy": "this.isBusy", "attr.role": "this.role", "attr.aria-haspopup": "this.haspopup", "attr.aria-invalid": "this.hostAriaInvalid" } }, providers: [
1460
- DROPDOWNLIST_VALUE_ACCESSOR,
1461
- DataService,
1462
- SelectionService,
1463
- NavigationService,
1464
- DisabledItemsService,
1465
- LocalizationService,
1466
- {
1467
- provide: L10N_PREFIX,
1468
- useValue: 'kendo.dropdownlist'
1469
- },
1470
- {
1471
- provide: FilterableComponent, useExisting: forwardRef(() => DropDownListComponent)
1472
- },
1473
- {
1474
- provide: KendoInput, useExisting: forwardRef(() => DropDownListComponent)
1475
- }
1476
- ], queries: [{ propertyName: "itemTemplate", first: true, predicate: ItemTemplateDirective, descendants: true }, { propertyName: "groupTemplate", first: true, predicate: GroupTemplateDirective, descendants: true }, { propertyName: "fixedGroupTemplate", first: true, predicate: FixedGroupTemplateDirective, descendants: true }, { propertyName: "valueTemplate", first: true, predicate: ValueTemplateDirective, descendants: true }, { propertyName: "headerTemplate", first: true, predicate: HeaderTemplateDirective, descendants: true }, { propertyName: "footerTemplate", first: true, predicate: FooterTemplateDirective, descendants: true }, { propertyName: "noDataTemplate", first: true, predicate: NoDataTemplateDirective, descendants: true }], viewQueries: [{ propertyName: "adaptiveRenderer", first: true, predicate: AdaptiveRendererComponent, descendants: true }, { propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }, { propertyName: "container", first: true, predicate: ["container"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "popupTemplate", first: true, predicate: ["popupTemplate"], descendants: true, static: true }, { propertyName: "optionsList", first: true, predicate: ["optionsList"], descendants: true }], exportAs: ["kendoDropDownList"], usesOnChanges: true, ngImport: i0, template: `
1477
- <ng-container kendoDropDownListLocalizedMessages
1478
- i18n-noDataText="kendo.dropdownlist.noDataText|The text displayed in the popup when there are no items"
1479
- noDataText="NO DATA FOUND"
1480
-
1481
- i18n-selectButtonText="kendo.dropdownlist.selectButtonText|The text set as aria-label on the select button"
1482
- selectButtonText="Select"
1483
-
1484
- i18n-filterInputLabel="kendo.dropdownlist.filterInputLabel|The text set as aria-label on the filter input"
1485
- filterInputLabel="Filter"
1486
-
1487
- i18n-popupLabel="kendo.dropdownlist.popupLabel|The label of the popup element that contains the list of options when its role is 'region'"
1488
- popupLabel="Options list"
1489
-
1490
- i18n-adaptiveCloseButtonTitle="kendo.dropdownlist.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"
1491
- adaptiveCloseButtonTitle="Close"
1492
-
1493
- i18n-filterPlaceholder="kendo.dropdownlist.filterPlaceholder|The text for the input's placeholder when filtering is enabled"
1494
- filterInputPlaceholder="Filter"
1495
- >
1496
- </ng-container>
1497
- <span class="k-input-inner" unselectable="on" [id]="valueLabelId" (click)="$event.preventDefault()">
1498
- <span class="k-input-value-text">
1499
- @if (valueTemplate) {
1500
- <ng-template
1501
- [templateContext]="{
1502
- templateRef: valueTemplate.templateRef,
1503
- $implicit: dataItem
1504
- }">
1505
- </ng-template>
1506
- }
1507
- @if (!valueTemplate) {{{ getText() }}}
1508
- </span>
1509
- </span>
1510
- @if (loading) {
1511
- <span class="k-i-loading k-input-loading-icon k-icon"></span>
1512
- }
1513
- <button
1514
- tabindex="-1"
1515
- unselectable="on"
1516
- type="button"
1517
- class="k-input-button k-button k-icon-button"
1518
- [ngClass]="selectButtonClasses"
1519
- [attr.aria-label]="messageFor('selectButtonText')"
1520
- [attr.disabled]="disabled ? '' : null"
1521
- [kendoEventsOutsideAngular]="{
1522
- mousedown: onMouseDown
1523
- }"
1524
- >
1525
- <kendo-icon-wrapper
1526
- unselectable="on"
1527
- [name]="icon || 'caret-alt-down'"
1528
- innerCssClass="k-button-icon"
1529
- [customFontClass]="customIconClass"
1530
- [svgIcon]="svgIcon || caretAltDownSVGIcon">
1531
- </kendo-icon-wrapper>
1532
- </button>
1533
- <ng-template #popupTemplate>
1534
- <ng-container *ngTemplateOutlet="sharedPopupActionSheetTemplate"></ng-container>
1535
- </ng-template>
1536
- @if (isOpen || isAdaptiveModeEnabled) {
1537
- <kendo-resize-sensor (resize)="onResize()"></kendo-resize-sensor>
1538
- }
1539
- <ng-container #container></ng-container>
1540
-
1541
- <kendo-adaptive-renderer
1542
- [sharedPopupActionSheetTemplate]="sharedPopupActionSheetTemplate"
1543
- [title]="adaptiveTitle"
1544
- [showTextInput]="filterable"
1545
- [subtitle]="adaptiveSubtitle"
1546
- (closePopup)="togglePopup(false)"
1547
- (textInputChange)="onFilterChange($event)"
1548
- [filterable]="filterable">
1549
- </kendo-adaptive-renderer>
1550
-
1551
- <ng-template #sharedPopupActionSheetTemplate>
1552
- <!--filterable-->
1553
- @if (filterable && !isActionSheetExpanded) {
1554
- <div class="k-list-filter" (click)="$event.stopImmediatePropagation()">
1555
- <span
1556
- class="k-searchbox k-input"
1557
- [ngClass]="filterInputClasses">
1558
- <kendo-icon-wrapper
1559
- class="k-icon"
1560
- innerCssClass="k-input-icon"
1561
- name="search"
1562
- [svgIcon]="searchIcon">
1563
- </kendo-icon-wrapper>
1564
- <input
1565
- #searchInput
1566
- role="searchbox"
1567
- aria-autocomplete="list"
1568
- aria-haspopup="listbox"
1569
- [attr.aria-controls]="listBoxId"
1570
- tabindex="-1"
1571
- [filterInput]="isFocused && !touchEnabled"
1572
- [attr.aria-label]="messageFor('filterInputLabel')"
1573
- [dir]="direction"
1574
- [(ngModel)]="filterText"
1575
- class="k-input-inner"
1576
- (keydown)="keydown($event, searchInput)"
1577
- (input)="handleFilter($event)"
1578
- (focus)="onFilterFocus()"
1579
- (blur)="blurFilterInput()"
1580
- (click)="handleClick()" />
1581
- </span>
1582
- </div>
1583
- }
1584
- <!--header template-->
1585
- @if (headerTemplate) {
1586
- <ng-template
1587
- [templateContext]="{
1588
- templateRef: headerTemplate.templateRef
1589
- }">
1590
- </ng-template>
1591
- }
1592
- <!--list-->
1593
- <kendo-list
1594
- #optionsList
1595
- [id]="listBoxId"
1596
- [size]="isAdaptive ? 'large' : size"
1597
- [rounded]="rounded"
1598
- [optionPrefix]="optionPrefix"
1599
- [data]="data"
1600
- [textField]="textField"
1601
- [valueField]="valueField"
1602
- [template]="itemTemplate"
1603
- [groupTemplate]="groupTemplate"
1604
- [fixedGroupTemplate]="fixedGroupTemplate"
1605
- [height]="listHeight"
1606
- [show]="isOpen"
1607
- [virtual]="virtual"
1608
- [ariaLive]="ariaLive"
1609
- [showStickyHeader]="showStickyHeader"
1610
- (pageChange)="pageChange($event)"
1611
- [defaultItem]="defaultItem">
1612
- </kendo-list>
1613
- <!--no-data template-->
1614
- @if (data.length === 0) {
1615
- <div class="k-no-data">
1616
- @if (noDataTemplate) {
1617
- <ng-template
1618
- [templateContext]="{
1619
- templateRef: noDataTemplate ? noDataTemplate.templateRef : undefined
1620
- }">
1621
- </ng-template>
1622
- }
1623
- @if (!noDataTemplate) {
1624
- <div>{{ messageFor('noDataText') }}</div>
1625
- }
1626
- </div>
1627
- }
1628
- <!--footer template-->
1629
- @if (footerTemplate) {
1630
- <ng-template
1631
- [templateContext]="{
1632
- templateRef: footerTemplate.templateRef
1633
- }">
1634
- </ng-template>
1635
- }
1636
- </ng-template>
1637
- `, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "\n [kendoDropDownListLocalizedMessages],\n [kendoDropDownTreeLocalizedMessages],\n [kendoComboBoxLocalizedMessages],\n [kendoMultiColumnComboBoxLocalizedMessages],\n [kendoAutoCompleteLocalizedMessages],\n [kendoMultiSelectLocalizedMessages],\n [kendoMultiSelectTreeLocalizedMessages]\n " }, { kind: "directive", type: TemplateContextDirective, selector: "[templateContext]", inputs: ["templateContext"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: EventsOutsideAngularDirective, selector: "[kendoEventsOutsideAngular]", inputs: ["kendoEventsOutsideAngular", "scope"] }, { 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: ResizeSensorComponent, selector: "kendo-resize-sensor", inputs: ["rateLimit"], outputs: ["resize"] }, { kind: "component", type: AdaptiveRendererComponent, selector: "kendo-adaptive-renderer", inputs: ["title", "subtitle", "showTextInput", "sharedPopupActionSheetTemplate", "text", "placeholder", "searchBarValue", "filterable"], outputs: ["closePopup", "textInputChange", "navigate", "onExpand"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i8.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i8.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: FilterInputDirective, selector: "[filterInput]", inputs: ["filterInput"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i8.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ListComponent, selector: "kendo-list", inputs: ["selected", "focused", "textField", "valueField", "height", "template", "groupTemplate", "fixedGroupTemplate", "show", "id", "optionPrefix", "multipleSelection", "virtual", "type", "checkboxes", "ariaLive", "isMultiselect", "isActionSheetExpanded", "showStickyHeader", "rowWidth", "customItemTemplate", "text", "allowCustom", "defaultItem", "data", "size", "rounded"], outputs: ["onClick", "pageChange", "listResize", "popupListScroll"] }] });
1638
- }
1639
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DropDownListComponent, decorators: [{
1640
- type: Component,
1641
- args: [{
1642
- exportAs: 'kendoDropDownList',
1643
- providers: [
1644
- DROPDOWNLIST_VALUE_ACCESSOR,
1645
- DataService,
1646
- SelectionService,
1647
- NavigationService,
1648
- DisabledItemsService,
1649
- LocalizationService,
1650
- {
1651
- provide: L10N_PREFIX,
1652
- useValue: 'kendo.dropdownlist'
1653
- },
1654
- {
1655
- provide: FilterableComponent, useExisting: forwardRef(() => DropDownListComponent)
1656
- },
1657
- {
1658
- provide: KendoInput, useExisting: forwardRef(() => DropDownListComponent)
1659
- }
1660
- ],
1661
- selector: 'kendo-dropdownlist',
1662
- template: `
1663
- <ng-container kendoDropDownListLocalizedMessages
1664
- i18n-noDataText="kendo.dropdownlist.noDataText|The text displayed in the popup when there are no items"
1665
- noDataText="NO DATA FOUND"
1666
-
1667
- i18n-selectButtonText="kendo.dropdownlist.selectButtonText|The text set as aria-label on the select button"
1668
- selectButtonText="Select"
1669
-
1670
- i18n-filterInputLabel="kendo.dropdownlist.filterInputLabel|The text set as aria-label on the filter input"
1671
- filterInputLabel="Filter"
1672
-
1673
- i18n-popupLabel="kendo.dropdownlist.popupLabel|The label of the popup element that contains the list of options when its role is 'region'"
1674
- popupLabel="Options list"
1675
-
1676
- i18n-adaptiveCloseButtonTitle="kendo.dropdownlist.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"
1677
- adaptiveCloseButtonTitle="Close"
1678
-
1679
- i18n-filterPlaceholder="kendo.dropdownlist.filterPlaceholder|The text for the input's placeholder when filtering is enabled"
1680
- filterInputPlaceholder="Filter"
1681
- >
1682
- </ng-container>
1683
- <span class="k-input-inner" unselectable="on" [id]="valueLabelId" (click)="$event.preventDefault()">
1684
- <span class="k-input-value-text">
1685
- @if (valueTemplate) {
1686
- <ng-template
1687
- [templateContext]="{
1688
- templateRef: valueTemplate.templateRef,
1689
- $implicit: dataItem
1690
- }">
1691
- </ng-template>
1692
- }
1693
- @if (!valueTemplate) {{{ getText() }}}
1694
- </span>
1695
- </span>
1696
- @if (loading) {
1697
- <span class="k-i-loading k-input-loading-icon k-icon"></span>
1698
- }
1699
- <button
1700
- tabindex="-1"
1701
- unselectable="on"
1702
- type="button"
1703
- class="k-input-button k-button k-icon-button"
1704
- [ngClass]="selectButtonClasses"
1705
- [attr.aria-label]="messageFor('selectButtonText')"
1706
- [attr.disabled]="disabled ? '' : null"
1707
- [kendoEventsOutsideAngular]="{
1708
- mousedown: onMouseDown
1709
- }"
1710
- >
1711
- <kendo-icon-wrapper
1712
- unselectable="on"
1713
- [name]="icon || 'caret-alt-down'"
1714
- innerCssClass="k-button-icon"
1715
- [customFontClass]="customIconClass"
1716
- [svgIcon]="svgIcon || caretAltDownSVGIcon">
1717
- </kendo-icon-wrapper>
1718
- </button>
1719
- <ng-template #popupTemplate>
1720
- <ng-container *ngTemplateOutlet="sharedPopupActionSheetTemplate"></ng-container>
1721
- </ng-template>
1722
- @if (isOpen || isAdaptiveModeEnabled) {
1723
- <kendo-resize-sensor (resize)="onResize()"></kendo-resize-sensor>
1724
- }
1725
- <ng-container #container></ng-container>
1726
-
1727
- <kendo-adaptive-renderer
1728
- [sharedPopupActionSheetTemplate]="sharedPopupActionSheetTemplate"
1729
- [title]="adaptiveTitle"
1730
- [showTextInput]="filterable"
1731
- [subtitle]="adaptiveSubtitle"
1732
- (closePopup)="togglePopup(false)"
1733
- (textInputChange)="onFilterChange($event)"
1734
- [filterable]="filterable">
1735
- </kendo-adaptive-renderer>
1736
-
1737
- <ng-template #sharedPopupActionSheetTemplate>
1738
- <!--filterable-->
1739
- @if (filterable && !isActionSheetExpanded) {
1740
- <div class="k-list-filter" (click)="$event.stopImmediatePropagation()">
1741
- <span
1742
- class="k-searchbox k-input"
1743
- [ngClass]="filterInputClasses">
1744
- <kendo-icon-wrapper
1745
- class="k-icon"
1746
- innerCssClass="k-input-icon"
1747
- name="search"
1748
- [svgIcon]="searchIcon">
1749
- </kendo-icon-wrapper>
1750
- <input
1751
- #searchInput
1752
- role="searchbox"
1753
- aria-autocomplete="list"
1754
- aria-haspopup="listbox"
1755
- [attr.aria-controls]="listBoxId"
1756
- tabindex="-1"
1757
- [filterInput]="isFocused && !touchEnabled"
1758
- [attr.aria-label]="messageFor('filterInputLabel')"
1759
- [dir]="direction"
1760
- [(ngModel)]="filterText"
1761
- class="k-input-inner"
1762
- (keydown)="keydown($event, searchInput)"
1763
- (input)="handleFilter($event)"
1764
- (focus)="onFilterFocus()"
1765
- (blur)="blurFilterInput()"
1766
- (click)="handleClick()" />
1767
- </span>
1768
- </div>
1769
- }
1770
- <!--header template-->
1771
- @if (headerTemplate) {
1772
- <ng-template
1773
- [templateContext]="{
1774
- templateRef: headerTemplate.templateRef
1775
- }">
1776
- </ng-template>
1777
- }
1778
- <!--list-->
1779
- <kendo-list
1780
- #optionsList
1781
- [id]="listBoxId"
1782
- [size]="isAdaptive ? 'large' : size"
1783
- [rounded]="rounded"
1784
- [optionPrefix]="optionPrefix"
1785
- [data]="data"
1786
- [textField]="textField"
1787
- [valueField]="valueField"
1788
- [template]="itemTemplate"
1789
- [groupTemplate]="groupTemplate"
1790
- [fixedGroupTemplate]="fixedGroupTemplate"
1791
- [height]="listHeight"
1792
- [show]="isOpen"
1793
- [virtual]="virtual"
1794
- [ariaLive]="ariaLive"
1795
- [showStickyHeader]="showStickyHeader"
1796
- (pageChange)="pageChange($event)"
1797
- [defaultItem]="defaultItem">
1798
- </kendo-list>
1799
- <!--no-data template-->
1800
- @if (data.length === 0) {
1801
- <div class="k-no-data">
1802
- @if (noDataTemplate) {
1803
- <ng-template
1804
- [templateContext]="{
1805
- templateRef: noDataTemplate ? noDataTemplate.templateRef : undefined
1806
- }">
1807
- </ng-template>
1808
- }
1809
- @if (!noDataTemplate) {
1810
- <div>{{ messageFor('noDataText') }}</div>
1811
- }
1812
- </div>
1813
- }
1814
- <!--footer template-->
1815
- @if (footerTemplate) {
1816
- <ng-template
1817
- [templateContext]="{
1818
- templateRef: footerTemplate.templateRef
1819
- }">
1820
- </ng-template>
1821
- }
1822
- </ng-template>
1823
- `,
1824
- standalone: true,
1825
- imports: [LocalizedMessagesDirective, TemplateContextDirective, NgClass, EventsOutsideAngularDirective, IconWrapperComponent, NgTemplateOutlet, ResizeSensorComponent, AdaptiveRendererComponent, ReactiveFormsModule, FilterInputDirective, FormsModule, ListComponent]
1826
- }]
1827
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.LocalizationService }, { type: i2.PopupService }, { type: i3.SelectionService }, { type: i4.NavigationService }, { type: i5.DisabledItemsService }, { type: i6.DataService }, { type: i0.NgZone }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: i0.Injector }, { type: i7.AdaptiveService }], propDecorators: { customIconClass: [{
1828
- type: Input
1829
- }], adaptiveRenderer: [{
1830
- type: ViewChild,
1831
- args: [AdaptiveRendererComponent]
1832
- }], searchInput: [{
1833
- type: ViewChild,
1834
- args: ['searchInput']
1835
- }], showStickyHeader: [{
1836
- type: Input
1837
- }], icon: [{
1838
- type: Input
1839
- }], svgIcon: [{
1840
- type: Input
1841
- }], loading: [{
1842
- type: Input
1843
- }], data: [{
1844
- type: Input
1845
- }], value: [{
1846
- type: Input
1847
- }], textField: [{
1848
- type: Input
1849
- }], valueField: [{
1850
- type: Input
1851
- }], adaptiveMode: [{
1852
- type: Input
1853
- }], adaptiveTitle: [{
1854
- type: Input
1855
- }], adaptiveSubtitle: [{
1856
- type: Input
1857
- }], popupSettings: [{
1858
- type: Input
1859
- }], listHeight: [{
1860
- type: Input
1861
- }], defaultItem: [{
1862
- type: Input
1863
- }], disabled: [{
1864
- type: Input
1865
- }], itemDisabled: [{
1866
- type: Input
1867
- }], readonly: [{
1868
- type: Input
1869
- }, {
1870
- type: HostBinding,
1871
- args: ['class.k-readonly']
1872
- }], filterable: [{
1873
- type: Input
1874
- }], virtual: [{
1875
- type: Input
1876
- }], ignoreCase: [{
1877
- type: Input
1878
- }], delay: [{
1879
- type: Input
1880
- }], valuePrimitive: [{
1881
- type: Input
1882
- }], tabindex: [{
1883
- type: Input
1884
- }], tabIndex: [{
1885
- type: Input,
1886
- args: ["tabIndex"]
1887
- }], size: [{
1888
- type: Input
1889
- }], rounded: [{
1890
- type: Input
1891
- }], fillMode: [{
1892
- type: Input
1893
- }], leftRightArrowsNavigation: [{
1894
- type: Input
1895
- }], valueChange: [{
1896
- type: Output
1897
- }], filterChange: [{
1898
- type: Output
1899
- }], selectionChange: [{
1900
- type: Output
1901
- }], open: [{
1902
- type: Output
1903
- }], opened: [{
1904
- type: Output
1905
- }], close: [{
1906
- type: Output
1907
- }], closed: [{
1908
- type: Output
1909
- }], onFocus: [{
1910
- type: Output,
1911
- args: ['focus']
1912
- }], onBlur: [{
1913
- type: Output,
1914
- args: ['blur']
1915
- }], itemTemplate: [{
1916
- type: ContentChild,
1917
- args: [ItemTemplateDirective, { static: false }]
1918
- }], groupTemplate: [{
1919
- type: ContentChild,
1920
- args: [GroupTemplateDirective, { static: false }]
1921
- }], fixedGroupTemplate: [{
1922
- type: ContentChild,
1923
- args: [FixedGroupTemplateDirective, { static: false }]
1924
- }], valueTemplate: [{
1925
- type: ContentChild,
1926
- args: [ValueTemplateDirective, { static: false }]
1927
- }], headerTemplate: [{
1928
- type: ContentChild,
1929
- args: [HeaderTemplateDirective, { static: false }]
1930
- }], footerTemplate: [{
1931
- type: ContentChild,
1932
- args: [FooterTemplateDirective, { static: false }]
1933
- }], noDataTemplate: [{
1934
- type: ContentChild,
1935
- args: [NoDataTemplateDirective, { static: false }]
1936
- }], container: [{
1937
- type: ViewChild,
1938
- args: ['container', { read: ViewContainerRef, static: true }]
1939
- }], popupTemplate: [{
1940
- type: ViewChild,
1941
- args: ['popupTemplate', { static: true }]
1942
- }], optionsList: [{
1943
- type: ViewChild,
1944
- args: ['optionsList', { static: false }]
1945
- }], hostClasses: [{
1946
- type: HostBinding,
1947
- args: ['class.k-dropdownlist']
1948
- }, {
1949
- type: HostBinding,
1950
- args: ['class.k-picker']
1951
- }], isDisabledClass: [{
1952
- type: HostBinding,
1953
- args: ['class.k-disabled']
1954
- }, {
1955
- type: HostBinding,
1956
- args: ['attr.aria-disabled']
1957
- }], isLoading: [{
1958
- type: HostBinding,
1959
- args: ['class.k-loading']
1960
- }], focusableId: [{
1961
- type: Input,
1962
- args: ['id']
1963
- }, {
1964
- type: HostBinding,
1965
- args: ['attr.id']
1966
- }], dir: [{
1967
- type: HostBinding,
1968
- args: ['attr.dir']
1969
- }], hostTabIndex: [{
1970
- type: HostBinding,
1971
- args: ['attr.tabindex']
1972
- }], readonlyClass: [{
1973
- type: HostBinding,
1974
- args: ['attr.readonly']
1975
- }], readonlyAttr: [{
1976
- type: HostBinding,
1977
- args: ['attr.readonly']
1978
- }], isBusy: [{
1979
- type: HostBinding,
1980
- args: ['attr.aria-busy']
1981
- }], role: [{
1982
- type: HostBinding,
1983
- args: ['attr.role']
1984
- }], haspopup: [{
1985
- type: HostBinding,
1986
- args: ['attr.aria-haspopup']
1987
- }], hostAriaInvalid: [{
1988
- type: HostBinding,
1989
- args: ['attr.aria-invalid']
1990
- }], keydown: [{
1991
- type: HostListener,
1992
- args: ['keydown', ['$event']]
1993
- }], keypress: [{
1994
- type: HostListener,
1995
- args: ['keypress', ['$event']]
1996
- }], click: [{
1997
- type: HostListener,
1998
- args: ['click']
1999
- }] } });