UNPKG

@progress/kendo-angular-dropdowns

Version:

A wide variety of native Angular dropdown components including AutoComplete, ComboBox, DropDownList, DropDownTree, MultiColumnComboBox, MultiSelect, and MultiSelectTree

717 lines (716 loc) 24.9 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ import { AfterContentChecked, ChangeDetectorRef, ElementRef, EventEmitter, Injector, NgZone, OnChanges, OnDestroy, OnInit, Renderer2, SimpleChanges, TemplateRef, ViewContainerRef } from '@angular/core'; import { ControlValueAccessor, FormControl } from '@angular/forms'; import { AdaptiveSize, AdaptiveService } from '@progress/kendo-angular-utils'; import { LocalizationService } from '@progress/kendo-angular-l10n'; import { NavigationService } from '../common/navigation/navigation.service'; import { PopupRef, PopupService } from '@progress/kendo-angular-popup'; import { DataBoundComponent, ExpandableComponent, NodeClickEvent, TreeItem, TreeViewComponent } from '@progress/kendo-angular-treeview'; import { PopupSettings } from '../common/models/popup-settings'; import { MultiSelectTreeCheckableSettings } from './checked-state/checkable-settings'; import { PreventableEvent } from '../common/models/preventable-event'; import { Direction } from '../common/models/direction'; import { RemoveTagEvent } from '../common/models/remove-tag-event'; import { CheckedItem } from './checked-state/checked-item'; import { AdaptiveMode } from '../common/util'; import { HeaderTemplateDirective } from '../common/templates/header-template.directive'; import { FooterTemplateDirective } from '../common/templates/footer-template.directive'; import { NodeTemplateDirective } from './templates/node-template.directive'; import { NoDataTemplateDirective } from '../common/templates/no-data-template.directive'; import { TagTemplateDirective } from '../common/templates/tag-template.directive'; import { GroupTagTemplateDirective } from '../common/templates/group-tag-template.directive'; import { Observable } from 'rxjs'; import { DropDownSize } from '../common/models/size'; import { DropDownRounded } from '../common/models/rounded'; import { DropDownFillMode } from '../common/models/fillmode'; import { MultiSelectTreeLookupService } from './lookup/lookup.service'; import { SVGIcon } from '@progress/kendo-svg-icons'; import { ActionSheetComponent } from '@progress/kendo-angular-navigation'; import { TextBoxComponent } from '@progress/kendo-angular-inputs'; import { AdaptiveRendererComponent } from '../common/adaptive-renderer.component'; import * as i0 from "@angular/core"; /** * Represents the Kendo UI for Angular [MultiSelectTree]({% slug overview_multiselecttree %}) component. * * The `MultiSelectTree` lets you select multiple items from hierarchical data in a tree structure. * It provides built-in filtering, checkboxes, and adaptive rendering for mobile devices. * * @example * ```typescript * @Component({ * selector: 'my-app', * template: ` * <kendo-multiselecttree * [data]="data" * textField="text" * valueField="value" * [(value)]="selectedValues"> * </kendo-multiselecttree> * ` * }) * export class AppComponent { * public data = [ * { text: 'Root', value: 1, items: [ * { text: 'Child 1', value: 2 }, * { text: 'Child 2', value: 3 } * ]} * ]; * public selectedValues = [2, 3]; * } * ``` * @remarks * Supported children components are: {@link CustomMessagesComponent}. */ export declare class MultiSelectTreeComponent implements OnInit, OnDestroy, OnChanges, AfterContentChecked, DataBoundComponent, ExpandableComponent, ControlValueAccessor { private injector; wrapper: ElementRef; private popupService; private renderer; private navigationService; private _zone; private localization; private cdr; private lookup; private adaptiveService; /** * @hidden */ touchEnabled: any; /** * @hidden */ animationDuration: number; /** * @hidden */ searchIcon: SVGIcon; /** * @hidden */ xIcon: SVGIcon; hostClasses: boolean; get isDisabled(): boolean | null; treeViewId: string; get hostAriaAutocomplete(): string; get isLoading(): boolean; get hostAriaInvalid(): boolean | null; get isBusy(): string; get id(): string; direction: Direction; get hostTabIndex(): number; role: string; ariaHasPopup: string; get isReadonly(): string; get ariaDescribedBy(): string; get ariaActiveDescendant(): string; /** * @hidden */ get formControl(): FormControl; /** * @hidden */ onFilterChange(text: any): void; /** * Controls the adaptive mode behavior of the component. * Set to `auto` to enable automatic adaptive rendering on small screens. * * @default 'none' */ adaptiveMode: AdaptiveMode; /** * Sets the title text for the ActionSheet in adaptive mode on small screens. * Uses the component label by default if not set. * * @default '' */ adaptiveTitle: string; /** * Sets the subtitle text for the ActionSheet in adaptive mode on small screens. * No subtitle appears by default. */ adaptiveSubtitle: string; /** * @hidden */ get isAdaptiveModeEnabled(): boolean; /** * @hidden */ windowSize: AdaptiveSize; /** * @hidden */ get isActionSheetExpanded(): boolean; /** * @hidden */ handleKeydown(event: any, input?: HTMLInputElement): void; /** * @hidden */ adaptiveRendererComponent: AdaptiveRendererComponent; /** * @hidden */ get actionSheet(): ActionSheetComponent; /** * @hidden */ get actionSheetSearchBar(): TextBoxComponent; /** * @hidden */ get isAdaptive(): boolean; headerTemplate: HeaderTemplateDirective; footerTemplate: FooterTemplateDirective; nodeTemplate: NodeTemplateDirective; noDataTemplate: NoDataTemplateDirective; tagTemplate: TagTemplateDirective; groupTagTemplate: GroupTagTemplateDirective; popupTemplate: TemplateRef<any>; container: ViewContainerRef; set treeview(treeview: TreeViewComponent); get treeview(): TreeViewComponent; private filterInput; private checkAllInput; /** * Sets the tab index for keyboard navigation. * Use `-1` to remove the component from the tab sequence. * * @default 0 */ set tabindex(value: number); get tabindex(): number; /** * Sets the visual size of the component. * * @default 'medium' */ set size(size: DropDownSize); get size(): DropDownSize; /** * Sets the border radius style of the component. * * @default 'medium' */ set rounded(rounded: DropDownRounded); get rounded(): DropDownRounded; /** * Sets the fill style for the component background and borders. * * @default 'solid' */ set fillMode(fillMode: DropDownFillMode); get fillMode(): DropDownFillMode; /** * Configures the popup container settings: animation, dimensions, styling and positioning. */ set popupSettings(settings: PopupSettings); get popupSettings(): PopupSettings; /** * Configures the checkbox behavior for the MultiSelecTree nodes. * Use `checkableSettings` to control parent-child selection relationships and click interactions. * * @default '{ checkChildren: true, checkOnClick: true }' */ set checkableSettings(settings: MultiSelectTreeCheckableSettings); get checkableSettings(): MultiSelectTreeCheckableSettings; /** * Sets the hierarchical data source for the tree structure. * Provide an array of objects that contain the tree data and structure. */ set data(data: Object[]); get data(): Object[]; /** * Sets the selected values in the component. * Accepts primitive values if `valuePrimitive` is `true`, or objects if `false`. */ set value(value: any[]); get value(): any[]; /** * Sets the data items that correspond to the selected values. * Required when using primitive values to resolve the full data objects. */ set dataItems(items: any[]); get dataItems(): any[]; /** * Specifies which data field provides the display text for tree nodes. * > The `textField` property can be set to point to a nested property value - e.g. `category.name`. */ textField: string | string[]; /** * Specifies which data field provides the unique values for tree nodes. * > The `valueField` property can be set to point to a nested property value - e.g. `category.id`. */ valueField: string | string[]; /** * Sets the levels in the data set where the values can be found when `valueField` is an Array. * The field serves to correctly allocate a data item used when the MultiSelectTree is initialized with a value. * * @default [] */ valueDepth: number[]; /** * Controls the loading state visual indicator. * Shows a loading spinner when set to `true`. * * @default false */ loading: boolean; /** * Sets the placeholder text shown when no items are selected. * Helps guide users on what action to take. * * @default '' */ placeholder: string; /** * Sets the maximum height of the options list in the popup. * Controls vertical scrolling when content exceeds this height. * * @default 200 */ set listHeight(_listHeight: number); get listHeight(): number; private _listHeight; /** * Controls whether the component accepts user input. * Prevents all user interactions when set to `true`. * * @default false */ disabled: boolean; /** * Sets the component to read-only mode. * Displays current selections but prevents changes. * * @default false */ readonly: boolean; /** * Determines the data type of selected values. * Set to `true` for primitive values, false for complex objects. * * @default false */ valuePrimitive: boolean; /** * Controls when child nodes load from the data source. * Set to `true` to load children only when parent nodes expand. * * @default false */ loadOnDemand: boolean; /** * Sets the unique identifier for the focusable element. * Used internally for accessibility and label association. */ focusableId: string; /** * Shows a clear button to reset all selections. * Appears on hover when selections exist and the component is not disabled. * * @default true */ clearButton: boolean; /** * Enables the built-in filter input for searching tree nodes. * Shows a search box above the tree when enabled. * * @default false */ filterable: boolean; /** * Shows a checkbox to select or deselect all visible tree nodes. * Appears above the tree when checkboxes are enabled. * * @default false */ checkAll: boolean; /** * Determines if a tree node contains child nodes. * Return `true` if the node has children, false otherwise. */ hasChildren: (node: object) => boolean; /** * Function that provides child nodes for a parent node. * Return an Observable of child objects for the given parent. */ fetchChildren: (node: object) => Observable<object[]>; /** * Determines if a specific node is expanded. The function is executed for each data item. */ isNodeExpanded: (item: object, index: string) => boolean; /** * Determines if a tree node should be hidden. */ isNodeVisible: (item: object, index: string) => boolean; /** * Determines if a tree node is disabled. The function is executed for each data item. */ itemDisabled: (item: object, index: string) => boolean; /** * @param { Any[] } dataItems - The selected data items from the list. * @returns { Any[] } - The tags that will be rendered by the component. * Transforms the provided array of data items into an array of tags. */ tagMapper: (tags: any) => any; /** * Fires when the component receives focus. */ onFocus: EventEmitter<any>; /** * Fires when the component gets blurred. */ onBlur: EventEmitter<any>; /** * Fires when the popup is about to open. ([See example]({% slug openstate_multiselecttree %})). * This event is preventable. When cancelled, the popup remains closed. */ open: EventEmitter<PreventableEvent>; /** * Fires after the popup opens completely. * Use this event to perform actions when the popup becomes visible. */ opened: EventEmitter<any>; /** * Fires before the popup closes. * Cancel this event to prevent the popup from closing. */ close: EventEmitter<PreventableEvent>; /** * Fires after the popup closes completely. * Use this event to perform cleanup actions when the popup becomes hidden. */ closed: EventEmitter<any>; /** * Fires when a tree node is expanded. * Use this event to respond to node expansion actions. */ nodeExpand: EventEmitter<TreeItem>; /** * Fires when a user collapses a tree node. * Use this event to respond to node collapse actions. */ nodeCollapse: EventEmitter<TreeItem>; /** * Fires when the selected value changes. * Use this event to respond to selection changes. */ valueChange: EventEmitter<any>; /** * Fires before a tag is removed. * Cancel this event to prevent tag removal. */ removeTag: EventEmitter<RemoveTagEvent>; /** * Fires when the filter input value changes. * Use this event to implement custom filtering logic. */ filterChange: EventEmitter<string>; /** * @hidden */ get focusedTagId(): string; set isFocused(isFocused: boolean); get isFocused(): boolean; /** * Returns the current open state. Returns `true` if the popup or actionSheet is open. */ get isOpen(): boolean; get width(): { min: string; max: string; }; get height(): string; get appendTo(): ViewContainerRef; /** * @hidden */ get popupContainerClasses(): Object; /** * @hidden * * Alias for `data`. Used for compatibility with the `DataBoundComponent` interface. * Required for the data-binding directives. */ set nodes(nodes: any[]); get nodes(): any[]; /** * @hidden * * Alias for `fetchChildren`. Used for compatibility with the `DataBoundComponent` interface. * Required for the data-binding directives */ set children(callback: (item: object) => Observable<object[]>); get children(): (item: object) => Observable<object[]>; /** * @hidden * * Alias for `nodeExpand`. Used for compatibility with the `ExpandableComponent` interface. * Required for the expand-directive. */ get expand(): EventEmitter<TreeItem>; /** * @hidden * * Alias for `nodeCollapse`. Used for compatibility with the `ExpandableComponent` interface. * Required for the expand-directive. */ get collapse(): EventEmitter<TreeItem>; /** * @hidden * * Alias for `isNodeExpanded`. Used for compatibility with the `ExpandableComponent` interface. * Required for the expand-directive. */ set isExpanded(callback: (item: object, index: string) => boolean); get isExpanded(): (item: object, index: string) => boolean; /** * @hidden * * Alias for `isNodeVisible`. Used for compatibility with the `DataBoundComponent` interface. * The `DataBoundComponent` interface is used in the data-binding directives. */ set isVisible(callback: (item: object, index: string) => boolean); get isVisible(): (item: object, index: string) => boolean; private get isTagFocused(); private get isTreeViewActive(); private get isWrapperActive(); private get isFilterActive(); private get isCheckAllActive(); /** * @hidden */ onResize(): void; /** * @hidden */ filterStateChange: EventEmitter<any>; /** * @hidden */ filter: string; /** * @hidden */ checkedItems: CheckedItem[]; /** * @hidden * The flag is needed in order to determine how to construct the items map keys. * If `true`, then the key consists of the item's value and level (depth), * else the key consists of the item's value and 0 (no leveling required) */ isHeterogeneous: boolean; /** * @hidden */ showAfter: number; /** * @hidden */ allNodesHidden: boolean; tagListId: string; tagPrefix: string; popupRef: PopupRef; tags: any[]; focusedTagIndex: number; disabledIndices: Set<number>; private _nodes; private _value; private _tabindex; private _popupSettings; private _checkableSettings; private _isFocused; private _treeview; private _dataItems; private _size; private _rounded; private _fillMode; private _searchableNodes; private _typedValue; private printableCharacters; private subs; private lastNodeOnFocus; private isContentInit; constructor(injector: Injector, wrapper: ElementRef, popupService: PopupService, renderer: Renderer2, navigationService: NavigationService, _zone: NgZone, localization: LocalizationService, cdr: ChangeDetectorRef, lookup: MultiSelectTreeLookupService, adaptiveService: AdaptiveService); ngOnInit(): void; ngAfterViewInit(): void; /** * @hidden */ ngOnDestroy(): void; /** * @hidden */ ngOnChanges(changes: SimpleChanges): void; /** * @hidden */ ngAfterContentChecked(): void; ngAfterContentInit(): void; /** * @hidden * * Used by the kendo-floatinglabel component to determine if the floating label * should be rendered inside the input when the component is not focused. */ isEmpty(): boolean; /** * Sets focus to the component. * Call this method to programmatically focus the MultiSelectTree. */ focus(): void; /** * Removes focus from the component. * Call this method to programmatically blur the MultiSelectTree. */ blur(): void; /** * Sets focus to a specific tree item by index. * Provide the item index in format like '1_1' to focus that item. * The item must be expanded and enabled to receive focus. */ focusItemAt(index: string): void; /** * Clears all selected values from the component. * This method does not trigger the valueChange event. */ reset(): void; /** * Opens or closes the popup programmatically. * Pass `true` to open, false to close, or omit the parameter to toggle. * This method does not trigger open or close events. */ toggle(open?: boolean): void; /** * @hidden */ handleFocus(event: FocusEvent): void; /** * @hidden */ handleBlur(e?: FocusEvent): void; /** * @hidden */ handleNodeClick(node: NodeClickEvent): void; /** * @hidden */ togglePopup(open: boolean): void; /** * @hidden */ messageFor(key: string): string; lastAction: 'check' | 'uncheck'; /** * @hidden */ handleCheckedItemsChange(items: CheckedItem[]): void; /** * @hidden */ handleRemoveTag({ tag, index }: { tag: any; index: number; }): void; /** * @hidden */ handleTagMapperChange(showAfter: number | string): void; /** * @hidden */ clearAll(event: any): void; /** * @hidden */ writeValue(value: any): void; /** * @hidden */ registerOnChange(fn: any): void; /** * @hidden */ registerOnTouched(fn: any): void; /** * @hidden */ setDisabledState(isDisabled: boolean): void; /** * @hidden */ handleFilterInputChange(input: Partial<HTMLInputElement>): void; /** * @hidden */ get filterInputClasses(): any; /** * @hidden */ get checkAllCheckboxClasses(): any; /** * @hidden */ toggleCheckAll(): void; protected onTouchedCallback: Function; protected onChangeCallback: Function; protected verifySettings(): void; private areNodesHidden; private emitValueChange; private triggerPopupEvents; private createPopup; private destroyPopup; private clearFilter; private handleClick; private subscribeEvents; private subscribeFocusEvents; private unSubscribeFocusEvents; private handleDocumentBlur; private handleTabKey; private handleUpKey; private handleDownKey; private handleRightKey; private handleLeftKey; private handleEnd; private handleHome; private handleBackspace; private handleDelete; private unsubscribeEvents; /** * Remove the `TreeView` from the tab order, otherwise a focus loop between the page elements will occur * and the user will not be able to tab to the rest of the browser elements */ private removeTreeViewFromTabOrder; private setState; private setTags; private updateValue; /** * @hidden */ onChildrenLoaded(): void; /** * @hidden * * Determines which of the provided tags should be disabled and stores their position indices */ private disabledItemsMapper; private setComponentClasses; private removeParents; /** * Creates an internal map of the available tree items to be used as a reference * to retrieve the item's children/parent and determine the checked sate */ private registerLookupItems; private registerChildLookupItems; private closeActionSheet; private openActionSheet; static ɵfac: i0.ɵɵFactoryDeclaration<MultiSelectTreeComponent, never>; static ɵcmp: i0.ɵɵComponentDeclaration<MultiSelectTreeComponent, "kendo-multiselecttree", ["kendoMultiSelectTree"], { "adaptiveMode": { "alias": "adaptiveMode"; "required": false; }; "adaptiveTitle": { "alias": "adaptiveTitle"; "required": false; }; "adaptiveSubtitle": { "alias": "adaptiveSubtitle"; "required": false; }; "tabindex": { "alias": "tabindex"; "required": false; }; "size": { "alias": "size"; "required": false; }; "rounded": { "alias": "rounded"; "required": false; }; "fillMode": { "alias": "fillMode"; "required": false; }; "popupSettings": { "alias": "popupSettings"; "required": false; }; "checkableSettings": { "alias": "checkableSettings"; "required": false; }; "data": { "alias": "data"; "required": false; }; "value": { "alias": "value"; "required": false; }; "dataItems": { "alias": "dataItems"; "required": false; }; "textField": { "alias": "textField"; "required": false; }; "valueField": { "alias": "valueField"; "required": false; }; "valueDepth": { "alias": "valueDepth"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "listHeight": { "alias": "listHeight"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "valuePrimitive": { "alias": "valuePrimitive"; "required": false; }; "loadOnDemand": { "alias": "loadOnDemand"; "required": false; }; "focusableId": { "alias": "focusableId"; "required": false; }; "clearButton": { "alias": "clearButton"; "required": false; }; "filterable": { "alias": "filterable"; "required": false; }; "checkAll": { "alias": "checkAll"; "required": false; }; "hasChildren": { "alias": "hasChildren"; "required": false; }; "fetchChildren": { "alias": "fetchChildren"; "required": false; }; "isNodeExpanded": { "alias": "isNodeExpanded"; "required": false; }; "isNodeVisible": { "alias": "isNodeVisible"; "required": false; }; "itemDisabled": { "alias": "itemDisabled"; "required": false; }; "tagMapper": { "alias": "tagMapper"; "required": false; }; }, { "onFocus": "focus"; "onBlur": "blur"; "open": "open"; "opened": "opened"; "close": "close"; "closed": "closed"; "nodeExpand": "nodeExpand"; "nodeCollapse": "nodeCollapse"; "valueChange": "valueChange"; "removeTag": "removeTag"; "filterChange": "filterChange"; }, ["headerTemplate", "footerTemplate", "nodeTemplate", "noDataTemplate", "tagTemplate", "groupTagTemplate"], never, true, never>; }