1162 lines
129 KiB
JavaScript
1162 lines
129 KiB
JavaScript
|
import { CommonModule } from '@angular/common';
|
||
|
import { booleanAttribute, ChangeDetectionStrategy, Component, ContentChildren, EventEmitter, forwardRef, Input, NgModule, Output, ViewChild, ViewEncapsulation } from '@angular/core';
|
||
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
||
|
import { PrimeTemplate, SharedModule } from 'primeng/api';
|
||
|
import { DomHandler } from 'primeng/dom';
|
||
|
import { ChevronDownIcon } from 'primeng/icons/chevrondown';
|
||
|
import { SearchIcon } from 'primeng/icons/search';
|
||
|
import { TimesIcon } from 'primeng/icons/times';
|
||
|
import { OverlayModule } from 'primeng/overlay';
|
||
|
import { RippleModule } from 'primeng/ripple';
|
||
|
import { TreeModule } from 'primeng/tree';
|
||
|
import { ObjectUtils, UniqueComponentId } from 'primeng/utils';
|
||
|
import { AutoFocusModule } from 'primeng/autofocus';
|
||
|
import * as i0 from "@angular/core";
|
||
|
import * as i1 from "primeng/api";
|
||
|
import * as i2 from "@angular/common";
|
||
|
import * as i3 from "primeng/overlay";
|
||
|
import * as i4 from "primeng/tree";
|
||
|
import * as i5 from "primeng/autofocus";
|
||
|
export const TREESELECT_VALUE_ACCESSOR = {
|
||
|
provide: NG_VALUE_ACCESSOR,
|
||
|
useExisting: forwardRef(() => TreeSelect),
|
||
|
multi: true
|
||
|
};
|
||
|
/**
|
||
|
* TreeSelect is a form component to choose from hierarchical data.
|
||
|
* @group Components
|
||
|
*/
|
||
|
export class TreeSelect {
|
||
|
config;
|
||
|
cd;
|
||
|
el;
|
||
|
overlayService;
|
||
|
/**
|
||
|
* Identifier of the underlying input element.
|
||
|
* @group Props
|
||
|
*/
|
||
|
inputId;
|
||
|
/**
|
||
|
* Height of the viewport, a scrollbar is defined if height of list exceeds this value.
|
||
|
* @group Props
|
||
|
*/
|
||
|
scrollHeight = '400px';
|
||
|
/**
|
||
|
* When present, it specifies that the component should be disabled.
|
||
|
* @group Props
|
||
|
*/
|
||
|
disabled;
|
||
|
/**
|
||
|
* Defines how multiple items can be selected, when true metaKey needs to be pressed to select or unselect an item and when set to false selection of each item can be toggled individually. On touch enabled devices, metaKeySelection is turned off automatically.
|
||
|
* @group Props
|
||
|
*/
|
||
|
metaKeySelection = false;
|
||
|
/**
|
||
|
* Specifies the input variant of the component.
|
||
|
* @group Props
|
||
|
*/
|
||
|
variant = 'outlined';
|
||
|
/**
|
||
|
* Defines how the selected items are displayed.
|
||
|
* @group Props
|
||
|
*/
|
||
|
display = 'comma';
|
||
|
/**
|
||
|
* Defines the selection mode.
|
||
|
* @group Props
|
||
|
*/
|
||
|
selectionMode = 'single';
|
||
|
/**
|
||
|
* Index of the element in tabbing order.
|
||
|
* @group Props
|
||
|
*/
|
||
|
tabindex = '0';
|
||
|
/**
|
||
|
* Defines a string that labels the input for accessibility.
|
||
|
* @group Props
|
||
|
*/
|
||
|
ariaLabel;
|
||
|
/**
|
||
|
* Establishes relationships between the component and label(s) where its value should be one or more element IDs.
|
||
|
* @group Props
|
||
|
*/
|
||
|
ariaLabelledBy;
|
||
|
/**
|
||
|
* Label to display when there are no selections.
|
||
|
* @group Props
|
||
|
*/
|
||
|
placeholder;
|
||
|
/**
|
||
|
* Style class of the overlay panel.
|
||
|
* @group Props
|
||
|
*/
|
||
|
panelClass;
|
||
|
/**
|
||
|
* Inline style of the panel element.
|
||
|
* @group Props
|
||
|
*/
|
||
|
panelStyle;
|
||
|
/**
|
||
|
* Style class of the panel element.
|
||
|
* @group Props
|
||
|
*/
|
||
|
panelStyleClass;
|
||
|
/**
|
||
|
* Inline style of the container element.
|
||
|
* @group Props
|
||
|
*/
|
||
|
containerStyle;
|
||
|
/**
|
||
|
* Style class of the container element.
|
||
|
* @group Props
|
||
|
*/
|
||
|
containerStyleClass;
|
||
|
/**
|
||
|
* Inline style of the label element.
|
||
|
* @group Props
|
||
|
*/
|
||
|
labelStyle;
|
||
|
/**
|
||
|
* Style class of the label element.
|
||
|
* @group Props
|
||
|
*/
|
||
|
labelStyleClass;
|
||
|
/**
|
||
|
* Specifies the options for the overlay.
|
||
|
* @group Props
|
||
|
*/
|
||
|
overlayOptions;
|
||
|
/**
|
||
|
* Text to display when there are no options available. Defaults to value from PrimeNG locale configuration.
|
||
|
* @group Props
|
||
|
*/
|
||
|
emptyMessage = '';
|
||
|
/**
|
||
|
* A valid query selector or an HTMLElement to specify where the overlay gets attached. Special keywords are "body" for document body and "self" for the element itself.
|
||
|
* @group Props
|
||
|
*/
|
||
|
appendTo;
|
||
|
/**
|
||
|
* When specified, displays an input field to filter the items.
|
||
|
* @group Props
|
||
|
*/
|
||
|
filter = false;
|
||
|
/**
|
||
|
* When filtering is enabled, filterBy decides which field or fields (comma separated) to search against.
|
||
|
* @group Props
|
||
|
*/
|
||
|
filterBy = 'label';
|
||
|
/**
|
||
|
* Mode for filtering valid values are "lenient" and "strict". Default is lenient.
|
||
|
* @group Props
|
||
|
*/
|
||
|
filterMode = 'lenient';
|
||
|
/**
|
||
|
* Placeholder text to show when filter input is empty.
|
||
|
* @group Props
|
||
|
*/
|
||
|
filterPlaceholder;
|
||
|
/**
|
||
|
* Locale to use in filtering. The default locale is the host environment's current locale.
|
||
|
* @group Props
|
||
|
*/
|
||
|
filterLocale;
|
||
|
/**
|
||
|
* Determines whether the filter input should be automatically focused when the component is rendered.
|
||
|
* @group Props
|
||
|
*/
|
||
|
filterInputAutoFocus = true;
|
||
|
/**
|
||
|
* Whether checkbox selections propagate to descendant nodes.
|
||
|
* @group Props
|
||
|
*/
|
||
|
propagateSelectionDown = true;
|
||
|
/**
|
||
|
* Whether checkbox selections propagate to ancestor nodes.
|
||
|
* @group Props
|
||
|
*/
|
||
|
propagateSelectionUp = true;
|
||
|
/**
|
||
|
* When enabled, a clear icon is displayed to clear the value.
|
||
|
* @group Props
|
||
|
*/
|
||
|
showClear = false;
|
||
|
/**
|
||
|
* Clears the filter value when hiding the dropdown.
|
||
|
* @group Props
|
||
|
*/
|
||
|
resetFilterOnHide = true;
|
||
|
/**
|
||
|
* Whether the data should be loaded on demand during scroll.
|
||
|
* @group Props
|
||
|
*/
|
||
|
virtualScroll;
|
||
|
/**
|
||
|
* Height of an item in the list for VirtualScrolling.
|
||
|
* @group Props
|
||
|
*/
|
||
|
virtualScrollItemSize;
|
||
|
/**
|
||
|
* Whether to use the scroller feature. The properties of scroller component can be used like an object in it.
|
||
|
* @group Props
|
||
|
*/
|
||
|
virtualScrollOptions;
|
||
|
/**
|
||
|
* When present, it specifies that the component should automatically get focus on load.
|
||
|
* @group Props
|
||
|
*/
|
||
|
autofocus;
|
||
|
/**
|
||
|
* An array of treenodes.
|
||
|
* @defaultValue undefined
|
||
|
* @group Props
|
||
|
*/
|
||
|
get options() {
|
||
|
return this._options;
|
||
|
}
|
||
|
set options(options) {
|
||
|
this._options = options;
|
||
|
this.updateTreeState();
|
||
|
}
|
||
|
/**
|
||
|
* Transition options of the show animation.
|
||
|
* @group Props
|
||
|
* @deprecated since v14.2.0 use overlayOptions property instead.
|
||
|
*/
|
||
|
get showTransitionOptions() {
|
||
|
return this._showTransitionOptions;
|
||
|
}
|
||
|
set showTransitionOptions(val) {
|
||
|
this._showTransitionOptions = val;
|
||
|
console.warn('The showTransitionOptions property is deprecated since v14.2.0, use overlayOptions property instead.');
|
||
|
}
|
||
|
/**
|
||
|
* Transition options of the hide animation.
|
||
|
* @group Props
|
||
|
* @deprecated since v14.2.0 use overlayOptions property instead.
|
||
|
*/
|
||
|
get hideTransitionOptions() {
|
||
|
return this._hideTransitionOptions;
|
||
|
}
|
||
|
set hideTransitionOptions(val) {
|
||
|
this._hideTransitionOptions = val;
|
||
|
console.warn('The hideTransitionOptions property is deprecated since v14.2.0, use overlayOptions property instead.');
|
||
|
}
|
||
|
/**
|
||
|
* Callback to invoke when a node is expanded.
|
||
|
* @param {TreeSelectNodeExpandEvent} event - Custom node expand event.
|
||
|
* @group Emits
|
||
|
*/
|
||
|
onNodeExpand = new EventEmitter();
|
||
|
/**
|
||
|
* Callback to invoke when a node is collapsed.
|
||
|
* @param {TreeSelectNodeCollapseEvent} event - Custom node collapse event.
|
||
|
* @group Emits
|
||
|
*/
|
||
|
onNodeCollapse = new EventEmitter();
|
||
|
/**
|
||
|
* Callback to invoke when the overlay is shown.
|
||
|
* @param {Event} event - Browser event.
|
||
|
* @group Emits
|
||
|
*/
|
||
|
onShow = new EventEmitter();
|
||
|
/**
|
||
|
* Callback to invoke when the overlay is hidden.
|
||
|
* @param {Event} event - Browser event.
|
||
|
* @group Emits
|
||
|
*/
|
||
|
onHide = new EventEmitter();
|
||
|
/**
|
||
|
* Callback to invoke when input field is cleared.
|
||
|
* @group Emits
|
||
|
*/
|
||
|
onClear = new EventEmitter();
|
||
|
/**
|
||
|
* Callback to invoke when data is filtered.
|
||
|
* @group Emits
|
||
|
*/
|
||
|
onFilter = new EventEmitter();
|
||
|
/**
|
||
|
* Callback to invoke when a node is unselected.
|
||
|
* @param {TreeNodeUnSelectEvent} event - node unselect event.
|
||
|
* @group Emits
|
||
|
*/
|
||
|
onNodeUnselect = new EventEmitter();
|
||
|
/**
|
||
|
* Callback to invoke when a node is selected.
|
||
|
* @param {TreeNodeSelectEvent} event - node select event.
|
||
|
* @group Emits
|
||
|
*/
|
||
|
onNodeSelect = new EventEmitter();
|
||
|
_showTransitionOptions;
|
||
|
_hideTransitionOptions;
|
||
|
templates;
|
||
|
containerEl;
|
||
|
focusInput;
|
||
|
filterViewChild;
|
||
|
treeViewChild;
|
||
|
panelEl;
|
||
|
overlayViewChild;
|
||
|
firstHiddenFocusableElementOnOverlay;
|
||
|
lastHiddenFocusableElementOnOverlay;
|
||
|
filteredNodes;
|
||
|
filterValue = null;
|
||
|
serializedValue;
|
||
|
valueTemplate;
|
||
|
headerTemplate;
|
||
|
emptyTemplate;
|
||
|
footerTemplate;
|
||
|
clearIconTemplate;
|
||
|
triggerIconTemplate;
|
||
|
filterIconTemplate;
|
||
|
closeIconTemplate;
|
||
|
itemTogglerIconTemplate;
|
||
|
itemCheckboxIconTemplate;
|
||
|
itemLoadingIconTemplate;
|
||
|
focused;
|
||
|
overlayVisible;
|
||
|
selfChange;
|
||
|
value;
|
||
|
expandedNodes = [];
|
||
|
_options;
|
||
|
templateMap;
|
||
|
onModelChange = () => { };
|
||
|
onModelTouched = () => { };
|
||
|
listId = '';
|
||
|
constructor(config, cd, el, overlayService) {
|
||
|
this.config = config;
|
||
|
this.cd = cd;
|
||
|
this.el = el;
|
||
|
this.overlayService = overlayService;
|
||
|
}
|
||
|
ngOnInit() {
|
||
|
this.listId = UniqueComponentId() + '_list';
|
||
|
this.updateTreeState();
|
||
|
}
|
||
|
ngAfterContentInit() {
|
||
|
if (this.templates.length) {
|
||
|
this.templateMap = {};
|
||
|
}
|
||
|
this.templates.forEach((item) => {
|
||
|
switch (item.getType()) {
|
||
|
case 'value':
|
||
|
this.valueTemplate = item.template;
|
||
|
break;
|
||
|
case 'header':
|
||
|
this.headerTemplate = item.template;
|
||
|
break;
|
||
|
case 'empty':
|
||
|
this.emptyTemplate = item.template;
|
||
|
break;
|
||
|
case 'footer':
|
||
|
this.footerTemplate = item.template;
|
||
|
break;
|
||
|
case 'clearicon':
|
||
|
this.clearIconTemplate = item.template;
|
||
|
break;
|
||
|
case 'triggericon':
|
||
|
this.triggerIconTemplate = item.template;
|
||
|
break;
|
||
|
case 'filtericon':
|
||
|
this.filterIconTemplate = item.template;
|
||
|
break;
|
||
|
case 'closeicon':
|
||
|
this.closeIconTemplate = item.template;
|
||
|
break;
|
||
|
case 'itemtogglericon':
|
||
|
this.itemTogglerIconTemplate = item.template;
|
||
|
break;
|
||
|
case 'itemcheckboxicon':
|
||
|
this.itemCheckboxIconTemplate = item.template;
|
||
|
break;
|
||
|
case 'itemloadingicon':
|
||
|
this.itemLoadingIconTemplate = item.template;
|
||
|
break;
|
||
|
default: //TODO: @deprecated Used "value" template instead
|
||
|
if (item.name)
|
||
|
this.templateMap[item.name] = item.template;
|
||
|
else
|
||
|
this.valueTemplate = item.template;
|
||
|
break;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
onOverlayAnimationStart(event) {
|
||
|
switch (event.toState) {
|
||
|
case 'visible':
|
||
|
if (this.filter) {
|
||
|
ObjectUtils.isNotEmpty(this.filterValue) && this.treeViewChild?._filter(this.filterValue);
|
||
|
this.filterInputAutoFocus && this.filterViewChild?.nativeElement.focus();
|
||
|
}
|
||
|
else {
|
||
|
let focusableElements = DomHandler.getFocusableElements(this.panelEl.nativeElement);
|
||
|
if (focusableElements && focusableElements.length > 0) {
|
||
|
focusableElements[0].focus();
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
onOverlayBeforeHide(event) {
|
||
|
let focusableElements = DomHandler.getFocusableElements(this.containerEl.nativeElement);
|
||
|
if (focusableElements && focusableElements.length > 0) {
|
||
|
focusableElements[0].focus();
|
||
|
}
|
||
|
}
|
||
|
onSelectionChange(event) {
|
||
|
this.value = event;
|
||
|
this.onModelChange(this.value);
|
||
|
this.cd.markForCheck();
|
||
|
}
|
||
|
onClick(event) {
|
||
|
if (this.disabled) {
|
||
|
return;
|
||
|
}
|
||
|
if (!this.overlayViewChild?.el?.nativeElement?.contains(event.target) &&
|
||
|
!DomHandler.hasClass(event.target, 'p-treeselect-close') &&
|
||
|
!DomHandler.hasClass(event.target, 'p-checkbox-box') &&
|
||
|
!DomHandler.hasClass(event.target, 'p-checkbox-icon')) {
|
||
|
if (this.overlayVisible) {
|
||
|
this.hide();
|
||
|
}
|
||
|
else {
|
||
|
this.show();
|
||
|
}
|
||
|
this.focusInput?.nativeElement.focus();
|
||
|
}
|
||
|
}
|
||
|
onKeyDown(event) {
|
||
|
switch (event.code) {
|
||
|
//down
|
||
|
case 'ArrowDown':
|
||
|
if (!this.overlayVisible) {
|
||
|
this.show();
|
||
|
event.preventDefault();
|
||
|
}
|
||
|
this.onArrowDown(event);
|
||
|
event.preventDefault();
|
||
|
break;
|
||
|
//space
|
||
|
case 'Space':
|
||
|
case 'Enter':
|
||
|
if (!this.overlayVisible) {
|
||
|
this.show();
|
||
|
event.preventDefault();
|
||
|
}
|
||
|
break;
|
||
|
//escape
|
||
|
case 'Escape':
|
||
|
if (this.overlayVisible) {
|
||
|
this.hide();
|
||
|
this.focusInput?.nativeElement.focus();
|
||
|
event.preventDefault();
|
||
|
}
|
||
|
break;
|
||
|
//tab
|
||
|
case 'Tab':
|
||
|
this.onTabKey(event);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
onFilterInput(event) {
|
||
|
this.filterValue = event.target.value;
|
||
|
this.treeViewChild?._filter(this.filterValue);
|
||
|
this.onFilter.emit({
|
||
|
filter: this.filterValue,
|
||
|
filteredValue: this.treeViewChild?.filteredNodes
|
||
|
});
|
||
|
setTimeout(() => {
|
||
|
this.overlayViewChild.alignOverlay();
|
||
|
});
|
||
|
}
|
||
|
onArrowDown(event) {
|
||
|
if (this.overlayVisible && this.panelEl?.nativeElement) {
|
||
|
let focusableElements = DomHandler.getFocusableElements(this.panelEl.nativeElement, '.p-treenode');
|
||
|
if (focusableElements && focusableElements.length > 0) {
|
||
|
focusableElements[0].focus();
|
||
|
}
|
||
|
event.preventDefault();
|
||
|
}
|
||
|
}
|
||
|
onFirstHiddenFocus(event) {
|
||
|
const focusableEl = event.relatedTarget === this.focusInput?.nativeElement ? DomHandler.getFirstFocusableElement(this.overlayViewChild?.overlayViewChild?.nativeElement, ':not([data-p-hidden-focusable="true"])') : this.focusInput?.nativeElement;
|
||
|
DomHandler.focus(focusableEl);
|
||
|
}
|
||
|
onLastHiddenFocus(event) {
|
||
|
const focusableEl = event.relatedTarget === this.focusInput?.nativeElement ? DomHandler.getLastFocusableElement(this.overlayViewChild?.overlayViewChild?.nativeElement, ':not([data-p-hidden-focusable="true"])') : this.focusInput?.nativeElement;
|
||
|
DomHandler.focus(focusableEl);
|
||
|
}
|
||
|
show() {
|
||
|
this.overlayVisible = true;
|
||
|
}
|
||
|
hide(event) {
|
||
|
this.overlayVisible = false;
|
||
|
this.resetFilter();
|
||
|
this.onHide.emit(event);
|
||
|
this.cd.markForCheck();
|
||
|
}
|
||
|
clear(event) {
|
||
|
this.value = null;
|
||
|
this.resetExpandedNodes();
|
||
|
this.resetPartialSelected();
|
||
|
this.onModelChange(this.value);
|
||
|
this.onClear.emit();
|
||
|
event.stopPropagation();
|
||
|
}
|
||
|
checkValue() {
|
||
|
return this.value !== null && ObjectUtils.isNotEmpty(this.value);
|
||
|
}
|
||
|
onTabKey(event, pressedInInputText = false) {
|
||
|
if (!pressedInInputText) {
|
||
|
if (this.overlayVisible && this.hasFocusableElements()) {
|
||
|
DomHandler.focus(event.shiftKey ? this.lastHiddenFocusableElementOnOverlay.nativeElement : this.firstHiddenFocusableElementOnOverlay.nativeElement);
|
||
|
event.preventDefault();
|
||
|
}
|
||
|
else {
|
||
|
this.overlayVisible && this.hide(this.filter);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
hasFocusableElements() {
|
||
|
return DomHandler.getFocusableElements(this.overlayViewChild.overlayViewChild.nativeElement, ':not([data-p-hidden-focusable="true"])').length > 0;
|
||
|
}
|
||
|
resetFilter() {
|
||
|
if (this.filter && !this.resetFilterOnHide) {
|
||
|
this.filteredNodes = this.treeViewChild?.filteredNodes;
|
||
|
this.treeViewChild?.resetFilter();
|
||
|
}
|
||
|
else {
|
||
|
this.filterValue = null;
|
||
|
}
|
||
|
}
|
||
|
updateTreeState() {
|
||
|
if (this.value) {
|
||
|
let selectedNodes = this.selectionMode === 'single' ? [this.value] : [...this.value];
|
||
|
this.resetExpandedNodes();
|
||
|
this.resetPartialSelected();
|
||
|
if (selectedNodes && this.options) {
|
||
|
this.updateTreeBranchState(null, null, selectedNodes);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
updateTreeBranchState(node, path, selectedNodes) {
|
||
|
if (node) {
|
||
|
if (this.isSelected(node)) {
|
||
|
this.expandPath(path);
|
||
|
selectedNodes.splice(selectedNodes.indexOf(node), 1);
|
||
|
}
|
||
|
if (selectedNodes.length > 0 && node.children) {
|
||
|
for (let childNode of node.children) {
|
||
|
this.updateTreeBranchState(childNode, [...path, node], selectedNodes);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
for (let childNode of this.options) {
|
||
|
this.updateTreeBranchState(childNode, [], selectedNodes);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
expandPath(expandedNodes) {
|
||
|
for (let node of expandedNodes) {
|
||
|
node.expanded = true;
|
||
|
}
|
||
|
this.expandedNodes = [...expandedNodes];
|
||
|
}
|
||
|
nodeExpand(event) {
|
||
|
this.onNodeExpand.emit(event);
|
||
|
this.expandedNodes.push(event.node);
|
||
|
}
|
||
|
nodeCollapse(event) {
|
||
|
this.onNodeCollapse.emit(event);
|
||
|
this.expandedNodes.splice(this.expandedNodes.indexOf(event.node), 1);
|
||
|
}
|
||
|
resetExpandedNodes() {
|
||
|
for (let node of this.expandedNodes) {
|
||
|
node.expanded = false;
|
||
|
}
|
||
|
this.expandedNodes = [];
|
||
|
}
|
||
|
resetPartialSelected(nodes = this.options) {
|
||
|
if (!nodes) {
|
||
|
return;
|
||
|
}
|
||
|
for (let node of nodes) {
|
||
|
node.partialSelected = false;
|
||
|
if (node.children && node.children?.length > 0) {
|
||
|
this.resetPartialSelected(node.children);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
findSelectedNodes(node, keys, selectedNodes) {
|
||
|
if (node) {
|
||
|
if (this.isSelected(node)) {
|
||
|
selectedNodes.push(node);
|
||
|
delete keys[node.key];
|
||
|
}
|
||
|
if (Object.keys(keys).length && node.children) {
|
||
|
for (let childNode of node.children) {
|
||
|
this.findSelectedNodes(childNode, keys, selectedNodes);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
for (let childNode of this.options) {
|
||
|
this.findSelectedNodes(childNode, keys, selectedNodes);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
isSelected(node) {
|
||
|
return this.findIndexInSelection(node) != -1;
|
||
|
}
|
||
|
findIndexInSelection(node) {
|
||
|
let index = -1;
|
||
|
if (this.value) {
|
||
|
if (this.selectionMode === 'single') {
|
||
|
let areNodesEqual = (this.value.key && this.value.key === node.key) || this.value == node;
|
||
|
index = areNodesEqual ? 0 : -1;
|
||
|
}
|
||
|
else {
|
||
|
for (let i = 0; i < this.value.length; i++) {
|
||
|
let selectedNode = this.value[i];
|
||
|
let areNodesEqual = (selectedNode.key && selectedNode.key === node.key) || selectedNode == node;
|
||
|
if (areNodesEqual) {
|
||
|
index = i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return index;
|
||
|
}
|
||
|
onSelect(event) {
|
||
|
this.onNodeSelect.emit(event);
|
||
|
if (this.selectionMode === 'single') {
|
||
|
// this.hide();
|
||
|
this.focusInput?.nativeElement.focus();
|
||
|
}
|
||
|
}
|
||
|
onUnselect(event) {
|
||
|
this.onNodeUnselect.emit(event);
|
||
|
}
|
||
|
onFocus() {
|
||
|
this.focused = true;
|
||
|
}
|
||
|
onBlur() {
|
||
|
this.focused = false;
|
||
|
}
|
||
|
writeValue(value) {
|
||
|
this.value = value;
|
||
|
this.updateTreeState();
|
||
|
this.cd.markForCheck();
|
||
|
}
|
||
|
registerOnChange(fn) {
|
||
|
this.onModelChange = fn;
|
||
|
}
|
||
|
registerOnTouched(fn) {
|
||
|
this.onModelTouched = fn;
|
||
|
}
|
||
|
setDisabledState(val) {
|
||
|
setTimeout(() => {
|
||
|
this.disabled = val;
|
||
|
this.cd.markForCheck();
|
||
|
});
|
||
|
}
|
||
|
containerClass() {
|
||
|
return {
|
||
|
'p-treeselect p-component p-inputwrapper': true,
|
||
|
'p-treeselect-chip': this.display === 'chip',
|
||
|
'p-disabled': this.disabled,
|
||
|
'p-focus': this.focused,
|
||
|
'p-variant-filled': this.variant === 'filled' || this.config.inputStyle() === 'filled'
|
||
|
};
|
||
|
}
|
||
|
labelClass() {
|
||
|
return {
|
||
|
'p-treeselect-label': true,
|
||
|
'p-placeholder': this.label === this.placeholder,
|
||
|
'p-treeselect-label-empty': !this.placeholder && this.emptyValue
|
||
|
};
|
||
|
}
|
||
|
get emptyValue() {
|
||
|
return !this.value || Object.keys(this.value).length === 0;
|
||
|
}
|
||
|
get emptyOptions() {
|
||
|
return !this.options || this.options.length === 0;
|
||
|
}
|
||
|
get label() {
|
||
|
let value = this.value || [];
|
||
|
return value.length ? value.map((node) => node.label).join(', ') : this.selectionMode === 'single' && this.value ? value.label : this.placeholder;
|
||
|
}
|
||
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: TreeSelect, deps: [{ token: i1.PrimeNGConfig }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: i1.OverlayService }], target: i0.ɵɵFactoryTarget.Component });
|
||
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "17.3.7", type: TreeSelect, selector: "p-treeSelect", inputs: { inputId: "inputId", scrollHeight: "scrollHeight", disabled: ["disabled", "disabled", booleanAttribute], metaKeySelection: ["metaKeySelection", "metaKeySelection", booleanAttribute], variant: "variant", display: "display", selectionMode: "selectionMode", tabindex: "tabindex", ariaLabel: "ariaLabel", ariaLabelledBy: "ariaLabelledBy", placeholder: "placeholder", panelClass: "panelClass", panelStyle: "panelStyle", panelStyleClass: "panelStyleClass", containerStyle: "containerStyle", containerStyleClass: "containerStyleClass", labelStyle: "labelStyle", labelStyleClass: "labelStyleClass", overlayOptions: "overlayOptions", emptyMessage: "emptyMessage", appendTo: "appendTo", filter: ["filter", "filter", booleanAttribute], filterBy: "filterBy", filterMode: "filterMode", filterPlaceholder: "filterPlaceholder", filterLocale: "filterLocale", filterInputAutoFocus: ["filterInputAutoFocus", "filterInputAutoFocus", booleanAttribute], propagateSelectionDown: ["propagateSelectionDown", "propagateSelectionDown", booleanAttribute], propagateSelectionUp: ["propagateSelectionUp", "propagateSelectionUp", booleanAttribute], showClear: ["showClear", "showClear", booleanAttribute], resetFilterOnHide: ["resetFilterOnHide", "resetFilterOnHide", booleanAttribute], virtualScroll: "virtualScroll", virtualScrollItemSize: "virtualScrollItemSize", virtualScrollOptions: "virtualScrollOptions", autofocus: ["autofocus", "autofocus", booleanAttribute], options: "options", showTransitionOptions: "showTransitionOptions", hideTransitionOptions: "hideTransitionOptions" }, outputs: { onNodeExpand: "onNodeExpand", onNodeCollapse: "onNodeCollapse", onShow: "onShow", onHide: "onHide", onClear: "onClear", onFilter: "onFilter", onNodeUnselect: "onNodeUnselect", onNodeSelect: "onNodeSelect" }, host: { properties: { "class.p-inputwrapper-filled": "!emptyValue", "class.p-inputwrapper-focus": "focused", "class.p-treeselect-clearable": "showClear && !disabled" }, classAttribute: "p-element p-inputwrapper" }, providers: [TREESELECT_VALUE_ACCESSOR], queries: [{ propertyName: "templates", predicate: PrimeTemplate }], viewQueries: [{ propertyName: "containerEl", first: true, predicate: ["container"], descendants: true }, { propertyName: "focusInput", first: true, predicate: ["focusInput"], descendants: true }, { propertyName: "filterViewChild", first: true, predicate: ["filter"], descendants: true }, { propertyName: "treeViewChild", first: true, predicate: ["tree"], descendants: true }, { propertyName: "panelEl", first: true, predicate: ["panel"], descendants: true }, { propertyName: "overlayViewChild", first: true, predicate: ["overlay"], descendants: true }, { propertyName: "firstHiddenFocusableElementOnOverlay", first: true, predicate: ["firstHiddenFocusableEl"], descendants: true }, { propertyName: "lastHiddenFocusableElementOnOverlay", first: true, predicate: ["lastHiddenFocusableEl"], descendants: true }], ngImport: i0, template: `
|
||
|
<div #container [ngClass]="containerClass()" [class]="containerStyleClass" [ngStyle]="containerStyle" (click)="onClick($event)">
|
||
|
<div class="p-hidden-accessible">
|
||
|
<input
|
||
|
#focusInput
|
||
|
type="text"
|
||
|
role="combobox"
|
||
|
[attr.id]="inputId"
|
||
|
readonly
|
||
|
[disabled]="disabled"
|
||
|
(focus)="onFocus()"
|
||
|
(blur)="onBlur()"
|
||
|
(keydown)="onKeyDown($event)"
|
||
|
[attr.tabindex]="!disabled ? tabindex : -1"
|
||
|
[attr.aria-controls]="overlayVisible ? listId : null"
|
||
|
[attr.aria-haspopup]="'tree'"
|
||
|
[attr.aria-expanded]="overlayVisible ?? false"
|
||
|
[attr.aria-labelledby]="ariaLabelledBy"
|
||
|
[attr.aria-label]="ariaLabel || (label === 'p-emptylabel' ? undefined : label)"
|
||
|
pAutoFocus
|
||
|
[autofocus]="autofocus"
|
||
|
/>
|
||
|
</div>
|
||
|
<div class="p-treeselect-label-container">
|
||
|
<div [ngClass]="labelClass()" [class]="labelStyleClass" [ngStyle]="labelStyle">
|
||
|
<ng-container *ngIf="valueTemplate; else defaultValueTemplate">
|
||
|
<ng-container *ngTemplateOutlet="valueTemplate; context: { $implicit: value, placeholder: placeholder }"></ng-container>
|
||
|
</ng-container>
|
||
|
<ng-template #defaultValueTemplate>
|
||
|
<ng-container *ngIf="display === 'comma'; else chipsValueTemplate">
|
||
|
{{ label || 'empty' }}
|
||
|
</ng-container>
|
||
|
<ng-template #chipsValueTemplate>
|
||
|
<div *ngFor="let node of value" class="p-treeselect-token">
|
||
|
<span class="p-treeselect-token-label">{{ node.label }}</span>
|
||
|
</div>
|
||
|
<ng-container *ngIf="emptyValue">{{ placeholder || 'empty' }}</ng-container>
|
||
|
</ng-template>
|
||
|
</ng-template>
|
||
|
</div>
|
||
|
<ng-container *ngIf="checkValue() && !disabled && showClear">
|
||
|
<TimesIcon *ngIf="!clearIconTemplate" [styleClass]="'p-treeselect-clear-icon'" (click)="clear($event)" />
|
||
|
<span *ngIf="clearIconTemplate" class="p-treeselect-clear-icon" (click)="clear($event)">
|
||
|
<ng-template *ngTemplateOutlet="clearIconTemplate"></ng-template>
|
||
|
</span>
|
||
|
</ng-container>
|
||
|
</div>
|
||
|
<div class="p-treeselect-trigger" role="button" aria-haspopup="tree" [attr.aria-expanded]="overlayVisible ?? false" [attr.aria-label]="'treeselect trigger'">
|
||
|
<ChevronDownIcon *ngIf="!triggerIconTemplate" [styleClass]="'p-treeselect-trigger-icon'" />
|
||
|
<span *ngIf="triggerIconTemplate" class="p-treeselect-trigger-icon">
|
||
|
<ng-template *ngTemplateOutlet="triggerIconTemplate"></ng-template>
|
||
|
</span>
|
||
|
</div>
|
||
|
<p-overlay
|
||
|
#overlay
|
||
|
[(visible)]="overlayVisible"
|
||
|
[options]="overlayOptions"
|
||
|
[target]="'@parent'"
|
||
|
[appendTo]="appendTo"
|
||
|
[showTransitionOptions]="showTransitionOptions"
|
||
|
[hideTransitionOptions]="hideTransitionOptions"
|
||
|
(onAnimationStart)="onOverlayAnimationStart($event)"
|
||
|
(onBeforeHide)="onOverlayBeforeHide($event)"
|
||
|
(onShow)="onShow.emit($event)"
|
||
|
(onHide)="hide($event)"
|
||
|
>
|
||
|
<ng-template pTemplate="content">
|
||
|
<div #panel [attr.id]="listId" class="p-treeselect-panel p-component" [ngStyle]="panelStyle" [class]="panelStyleClass" [ngClass]="panelClass">
|
||
|
<span
|
||
|
#firstHiddenFocusableEl
|
||
|
role="presentation"
|
||
|
class="p-hidden-accessible p-hidden-focusable"
|
||
|
[attr.tabindex]="0"
|
||
|
(focus)="onFirstHiddenFocus($event)"
|
||
|
[attr.data-p-hidden-accessible]="true"
|
||
|
[attr.data-p-hidden-focusable]="true"
|
||
|
>
|
||
|
</span>
|
||
|
<ng-container *ngTemplateOutlet="headerTemplate; context: { $implicit: value, options: options }"></ng-container>
|
||
|
<div class="p-treeselect-header" *ngIf="filter" (keydown.arrowdown)="onArrowDown($event)">
|
||
|
<div class="p-treeselect-filter-container">
|
||
|
<input
|
||
|
#filter
|
||
|
type="search"
|
||
|
autocomplete="off"
|
||
|
class="p-treeselect-filter p-inputtext p-component"
|
||
|
[attr.placeholder]="filterPlaceholder"
|
||
|
(keydown.enter)="$event.preventDefault()"
|
||
|
(input)="onFilterInput($event)"
|
||
|
[value]="filterValue"
|
||
|
/>
|
||
|
<SearchIcon *ngIf="!filterIconTemplate" [styleClass]="'p-treeselect-filter-icon'" />
|
||
|
<span *ngIf="filterIconTemplate" class="p-treeselect-filter-icon">
|
||
|
<ng-template *ngTemplateOutlet="filterIconTemplate"></ng-template>
|
||
|
</span>
|
||
|
</div>
|
||
|
<button class="p-treeselect-close p-link" (click)="hide()">
|
||
|
<TimesIcon *ngIf="!closeIconTemplate" />
|
||
|
<span *ngIf="closeIconTemplate">
|
||
|
<ng-template *ngTemplateOutlet="closeIconTemplate"></ng-template>
|
||
|
</span>
|
||
|
</button>
|
||
|
</div>
|
||
|
<div class="p-treeselect-items-wrapper" [ngStyle]="{ 'max-height': scrollHeight }">
|
||
|
<p-tree
|
||
|
#tree
|
||
|
[value]="options"
|
||
|
[propagateSelectionDown]="propagateSelectionDown"
|
||
|
[propagateSelectionUp]="propagateSelectionUp"
|
||
|
[selectionMode]="selectionMode"
|
||
|
(selectionChange)="onSelectionChange($event)"
|
||
|
[selection]="value"
|
||
|
[metaKeySelection]="metaKeySelection"
|
||
|
(onNodeExpand)="nodeExpand($event)"
|
||
|
(onNodeCollapse)="nodeCollapse($event)"
|
||
|
(onNodeSelect)="onSelect($event)"
|
||
|
[emptyMessage]="emptyMessage"
|
||
|
(onNodeUnselect)="onUnselect($event)"
|
||
|
[filterBy]="filterBy"
|
||
|
[filterMode]="filterMode"
|
||
|
[filterPlaceholder]="filterPlaceholder"
|
||
|
[filterLocale]="filterLocale"
|
||
|
[filteredNodes]="filteredNodes"
|
||
|
[virtualScroll]="virtualScroll"
|
||
|
[virtualScrollItemSize]="virtualScrollItemSize"
|
||
|
[virtualScrollOptions]="virtualScrollOptions"
|
||
|
[_templateMap]="templateMap"
|
||
|
>
|
||
|
<ng-container *ngIf="emptyTemplate">
|
||
|
<ng-template pTemplate="empty">
|
||
|
<ng-container *ngTemplateOutlet="emptyTemplate"></ng-container>
|
||
|
</ng-template>
|
||
|
</ng-container>
|
||
|
<ng-template pTemplate="togglericon" let-expanded *ngIf="itemTogglerIconTemplate">
|
||
|
<ng-container *ngTemplateOutlet="itemTogglerIconTemplate; context: { $implicit: expanded }"></ng-container>
|
||
|
</ng-template>
|
||
|
<ng-template pTemplate="checkboxicon" let-selected let-partialSelected="partialSelected" *ngIf="itemCheckboxIconTemplate">
|
||
|
<ng-container *ngTemplateOutlet="itemCheckboxIconTemplate; context: { $implicit: selected, partialSelected: partialSelected }"></ng-container>
|
||
|
</ng-template>
|
||
|
<ng-template pTemplate="loadingicon" *ngIf="itemLoadingIconTemplate">
|
||
|
<ng-container *ngTemplateOutlet="itemLoadingIconTemplate"></ng-container>
|
||
|
</ng-template>
|
||
|
</p-tree>
|
||
|
</div>
|
||
|
<ng-container *ngTemplateOutlet="footerTemplate; context: { $implicit: value, options: options }"></ng-container>
|
||
|
<span
|
||
|
#lastHiddenFocusableEl
|
||
|
role="presentation"
|
||
|
class="p-hidden-accessible p-hidden-focusable"
|
||
|
[attr.tabindex]="0"
|
||
|
(focus)="onLastHiddenFocus($event)"
|
||
|
[attr.data-p-hidden-accessible]="true"
|
||
|
[attr.data-p-hidden-focusable]="true"
|
||
|
></span>
|
||
|
</div>
|
||
|
</ng-template>
|
||
|
</p-overlay>
|
||
|
</div>
|
||
|
`, isInline: true, styles: ["@layer primeng{.p-treeselect{display:inline-flex;cursor:pointer;position:relative;-webkit-user-select:none;user-select:none}.p-treeselect-trigger{display:flex;align-items:center;justify-content:center;flex-shrink:0}.p-treeselect-label-container{overflow:hidden;flex:1 1 auto;cursor:pointer;display:flex}.p-treeselect-label{display:block;white-space:nowrap;cursor:pointer;overflow:hidden;text-overflow:ellipsis}.p-treeselect-label-empty{overflow:hidden;visibility:hidden}.p-treeselect-token{cursor:default;display:inline-flex;align-items:center;flex:0 0 auto}.p-treeselect-items-wrapper{overflow:auto}.p-treeselect-header{display:flex;align-items:center;justify-content:space-between}.p-treeselect-filter-container{position:relative;flex:1 1 auto}.p-treeselect-filter-icon{position:absolute;top:50%;margin-top:-.5rem}.p-treeselect-filter-container .p-inputtext{width:100%}.p-treeselect-close{display:flex;align-items:center;justify-content:center;flex-shrink:0;overflow:hidden;position:relative;margin-left:auto}.p-treeselect-clear-icon{position:absolute;top:50%;margin-top:-.5rem}.p-fluid .p-treeselect{display:flex}.p-treeselect-clear-icon{position:absolute;top:50%;margin-top:-.5rem;cursor:pointer}.p-treeselect-clearable{position:relative}}\n"], dependencies: [{ kind: "directive", type: i0.forwardRef(() => i2.NgClass), selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i0.forwardRef(() => i2.NgForOf), selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i0.forwardRef(() => i2.NgIf), selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i0.forwardRef(() => i2.NgTemplateOutlet), selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i0.forwardRef(() => i2.NgStyle), selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i0.forwardRef(() => i3.Overlay), selector: "p-overlay", inputs: ["visible", "mode", "style", "styleClass", "contentStyle", "contentStyleClass", "target", "appendTo", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "listener", "responsive", "options"], outputs: ["visibleChange", "onBeforeShow", "onShow", "onBeforeHide", "onHide", "onAnimationStart", "onAnimationDone"] }, { kind: "directive", type: i0.forwardRef(() => i1.PrimeTemplate), selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: i0.forwardRef(() => i4.Tree), selector: "p-tree", inputs: ["value", "selectionMode", "loadingMode", "selection", "style", "styleClass", "contextMenu", "layout", "draggableScope", "droppableScope", "draggableNodes", "droppableNodes", "metaKeySelection", "propagateSelectionUp", "propagateSelectionDown", "loading", "loadingIcon", "emptyMessage", "ariaLabel", "togglerAriaLabel", "ariaLabelledBy", "validateDrop", "filter", "filterBy", "filterMode", "filterPlaceholder", "filteredNodes", "filterLocale", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "indentation", "_templateMap", "trackBy", "virtualNodeHeight"], outputs: ["selectionChange", "onNodeSelect", "onNodeUnselect", "onNodeExpand", "onNodeCollapse", "onNodeContextMenuSelect", "onNodeDrop", "onLazyLoad", "onScroll", "onScrollIndexChange", "onFilter"] }, { kind: "directive", type: i0.forwardRef(() => i5.AutoFocus), selector: "[pAutoFocus]", inputs: ["autofocus"] }, { kind: "component", type: i0.forwardRef(() => SearchIcon), selector: "SearchIcon" }, { kind: "component", type: i0.forwardRef(() => TimesIcon), selector: "TimesIcon" }, { kind: "component", type: i0.forwardRef(() => ChevronDownIcon), selector: "ChevronDownIcon" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
||
|
}
|
||
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: TreeSelect, decorators: [{
|
||
|
type: Component,
|
||
|
args: [{ selector: 'p-treeSelect', template: `
|
||
|
<div #container [ngClass]="containerClass()" [class]="containerStyleClass" [ngStyle]="containerStyle" (click)="onClick($event)">
|
||
|
<div class="p-hidden-accessible">
|
||
|
<input
|
||
|
#focusInput
|
||
|
type="text"
|
||
|
role="combobox"
|
||
|
[attr.id]="inputId"
|
||
|
readonly
|
||
|
[disabled]="disabled"
|
||
|
(focus)="onFocus()"
|
||
|
(blur)="onBlur()"
|
||
|
(keydown)="onKeyDown($event)"
|
||
|
[attr.tabindex]="!disabled ? tabindex : -1"
|
||
|
[attr.aria-controls]="overlayVisible ? listId : null"
|
||
|
[attr.aria-haspopup]="'tree'"
|
||
|
[attr.aria-expanded]="overlayVisible ?? false"
|
||
|
[attr.aria-labelledby]="ariaLabelledBy"
|
||
|
[attr.aria-label]="ariaLabel || (label === 'p-emptylabel' ? undefined : label)"
|
||
|
pAutoFocus
|
||
|
[autofocus]="autofocus"
|
||
|
/>
|
||
|
</div>
|
||
|
<div class="p-treeselect-label-container">
|
||
|
<div [ngClass]="labelClass()" [class]="labelStyleClass" [ngStyle]="labelStyle">
|
||
|
<ng-container *ngIf="valueTemplate; else defaultValueTemplate">
|
||
|
<ng-container *ngTemplateOutlet="valueTemplate; context: { $implicit: value, placeholder: placeholder }"></ng-container>
|
||
|
</ng-container>
|
||
|
<ng-template #defaultValueTemplate>
|
||
|
<ng-container *ngIf="display === 'comma'; else chipsValueTemplate">
|
||
|
{{ label || 'empty' }}
|
||
|
</ng-container>
|
||
|
<ng-template #chipsValueTemplate>
|
||
|
<div *ngFor="let node of value" class="p-treeselect-token">
|
||
|
<span class="p-treeselect-token-label">{{ node.label }}</span>
|
||
|
</div>
|
||
|
<ng-container *ngIf="emptyValue">{{ placeholder || 'empty' }}</ng-container>
|
||
|
</ng-template>
|
||
|
</ng-template>
|
||
|
</div>
|
||
|
<ng-container *ngIf="checkValue() && !disabled && showClear">
|
||
|
<TimesIcon *ngIf="!clearIconTemplate" [styleClass]="'p-treeselect-clear-icon'" (click)="clear($event)" />
|
||
|
<span *ngIf="clearIconTemplate" class="p-treeselect-clear-icon" (click)="clear($event)">
|
||
|
<ng-template *ngTemplateOutlet="clearIconTemplate"></ng-template>
|
||
|
</span>
|
||
|
</ng-container>
|
||
|
</div>
|
||
|
<div class="p-treeselect-trigger" role="button" aria-haspopup="tree" [attr.aria-expanded]="overlayVisible ?? false" [attr.aria-label]="'treeselect trigger'">
|
||
|
<ChevronDownIcon *ngIf="!triggerIconTemplate" [styleClass]="'p-treeselect-trigger-icon'" />
|
||
|
<span *ngIf="triggerIconTemplate" class="p-treeselect-trigger-icon">
|
||
|
<ng-template *ngTemplateOutlet="triggerIconTemplate"></ng-template>
|
||
|
</span>
|
||
|
</div>
|
||
|
<p-overlay
|
||
|
#overlay
|
||
|
[(visible)]="overlayVisible"
|
||
|
[options]="overlayOptions"
|
||
|
[target]="'@parent'"
|
||
|
[appendTo]="appendTo"
|
||
|
[showTransitionOptions]="showTransitionOptions"
|
||
|
[hideTransitionOptions]="hideTransitionOptions"
|
||
|
(onAnimationStart)="onOverlayAnimationStart($event)"
|
||
|
(onBeforeHide)="onOverlayBeforeHide($event)"
|
||
|
(onShow)="onShow.emit($event)"
|
||
|
(onHide)="hide($event)"
|
||
|
>
|
||
|
<ng-template pTemplate="content">
|
||
|
<div #panel [attr.id]="listId" class="p-treeselect-panel p-component" [ngStyle]="panelStyle" [class]="panelStyleClass" [ngClass]="panelClass">
|
||
|
<span
|
||
|
#firstHiddenFocusableEl
|
||
|
role="presentation"
|
||
|
class="p-hidden-accessible p-hidden-focusable"
|
||
|
[attr.tabindex]="0"
|
||
|
(focus)="onFirstHiddenFocus($event)"
|
||
|
[attr.data-p-hidden-accessible]="true"
|
||
|
[attr.data-p-hidden-focusable]="true"
|
||
|
>
|
||
|
</span>
|
||
|
<ng-container *ngTemplateOutlet="headerTemplate; context: { $implicit: value, options: options }"></ng-container>
|
||
|
<div class="p-treeselect-header" *ngIf="filter" (keydown.arrowdown)="onArrowDown($event)">
|
||
|
<div class="p-treeselect-filter-container">
|
||
|
<input
|
||
|
#filter
|
||
|
type="search"
|
||
|
autocomplete="off"
|
||
|
class="p-treeselect-filter p-inputtext p-component"
|
||
|
[attr.placeholder]="filterPlaceholder"
|
||
|
(keydown.enter)="$event.preventDefault()"
|
||
|
(input)="onFilterInput($event)"
|
||
|
[value]="filterValue"
|
||
|
/>
|
||
|
<SearchIcon *ngIf="!filterIconTemplate" [styleClass]="'p-treeselect-filter-icon'" />
|
||
|
<span *ngIf="filterIconTemplate" class="p-treeselect-filter-icon">
|
||
|
<ng-template *ngTemplateOutlet="filterIconTemplate"></ng-template>
|
||
|
</span>
|
||
|
</div>
|
||
|
<button class="p-treeselect-close p-link" (click)="hide()">
|
||
|
<TimesIcon *ngIf="!closeIconTemplate" />
|
||
|
<span *ngIf="closeIconTemplate">
|
||
|
<ng-template *ngTemplateOutlet="closeIconTemplate"></ng-template>
|
||
|
</span>
|
||
|
</button>
|
||
|
</div>
|
||
|
<div class="p-treeselect-items-wrapper" [ngStyle]="{ 'max-height': scrollHeight }">
|
||
|
<p-tree
|
||
|
#tree
|
||
|
[value]="options"
|
||
|
[propagateSelectionDown]="propagateSelectionDown"
|
||
|
[propagateSelectionUp]="propagateSelectionUp"
|
||
|
[selectionMode]="selectionMode"
|
||
|
(selectionChange)="onSelectionChange($event)"
|
||
|
[selection]="value"
|
||
|
[metaKeySelection]="metaKeySelection"
|
||
|
(onNodeExpand)="nodeExpand($event)"
|
||
|
(onNodeCollapse)="nodeCollapse($event)"
|
||
|
(onNodeSelect)="onSelect($event)"
|
||
|
[emptyMessage]="emptyMessage"
|
||
|
(onNodeUnselect)="onUnselect($event)"
|
||
|
[filterBy]="filterBy"
|
||
|
[filterMode]="filterMode"
|
||
|
[filterPlaceholder]="filterPlaceholder"
|
||
|
[filterLocale]="filterLocale"
|
||
|
[filteredNodes]="filteredNodes"
|
||
|
[virtualScroll]="virtualScroll"
|
||
|
[virtualScrollItemSize]="virtualScrollItemSize"
|
||
|
[virtualScrollOptions]="virtualScrollOptions"
|
||
|
[_templateMap]="templateMap"
|
||
|
>
|
||
|
<ng-container *ngIf="emptyTemplate">
|
||
|
<ng-template pTemplate="empty">
|
||
|
<ng-container *ngTemplateOutlet="emptyTemplate"></ng-container>
|
||
|
</ng-template>
|
||
|
</ng-container>
|
||
|
<ng-template pTemplate="togglericon" let-expanded *ngIf="itemTogglerIconTemplate">
|
||
|
<ng-container *ngTemplateOutlet="itemTogglerIconTemplate; context: { $implicit: expanded }"></ng-container>
|
||
|
</ng-template>
|
||
|
<ng-template pTemplate="checkboxicon" let-selected let-partialSelected="partialSelected" *ngIf="itemCheckboxIconTemplate">
|
||
|
<ng-container *ngTemplateOutlet="itemCheckboxIconTemplate; context: { $implicit: selected, partialSelected: partialSelected }"></ng-container>
|
||
|
</ng-template>
|
||
|
<ng-template pTemplate="loadingicon" *ngIf="itemLoadingIconTemplate">
|
||
|
<ng-container *ngTemplateOutlet="itemLoadingIconTemplate"></ng-container>
|
||
|
</ng-template>
|
||
|
</p-tree>
|
||
|
</div>
|
||
|
<ng-container *ngTemplateOutlet="footerTemplate; context: { $implicit: value, options: options }"></ng-container>
|
||
|
<span
|
||
|
#lastHiddenFocusableEl
|
||
|
role="presentation"
|
||
|
class="p-hidden-accessible p-hidden-focusable"
|
||
|
[attr.tabindex]="0"
|
||
|
(focus)="onLastHiddenFocus($event)"
|
||
|
[attr.data-p-hidden-accessible]="true"
|
||
|
[attr.data-p-hidden-focusable]="true"
|
||
|
></span>
|
||
|
</div>
|
||
|
</ng-template>
|
||
|
</p-overlay>
|
||
|
</div>
|
||
|
`, host: {
|
||
|
class: 'p-element p-inputwrapper',
|
||
|
'[class.p-inputwrapper-filled]': '!emptyValue',
|
||
|
'[class.p-inputwrapper-focus]': 'focused',
|
||
|
'[class.p-treeselect-clearable]': 'showClear && !disabled'
|
||
|
}, changeDetection: ChangeDetectionStrategy.OnPush, providers: [TREESELECT_VALUE_ACCESSOR], encapsulation: ViewEncapsulation.None, styles: ["@layer primeng{.p-treeselect{display:inline-flex;cursor:pointer;position:relative;-webkit-user-select:none;user-select:none}.p-treeselect-trigger{display:flex;align-items:center;justify-content:center;flex-shrink:0}.p-treeselect-label-container{overflow:hidden;flex:1 1 auto;cursor:pointer;display:flex}.p-treeselect-label{display:block;white-space:nowrap;cursor:pointer;overflow:hidden;text-overflow:ellipsis}.p-treeselect-label-empty{overflow:hidden;visibility:hidden}.p-treeselect-token{cursor:default;display:inline-flex;align-items:center;flex:0 0 auto}.p-treeselect-items-wrapper{overflow:auto}.p-treeselect-header{display:flex;align-items:center;justify-content:space-between}.p-treeselect-filter-container{position:relative;flex:1 1 auto}.p-treeselect-filter-icon{position:absolute;top:50%;margin-top:-.5rem}.p-treeselect-filter-container .p-inputtext{width:100%}.p-treeselect-close{display:flex;align-items:center;justify-content:center;flex-shrink:0;overflow:hidden;position:relative;margin-left:auto}.p-treeselect-clear-icon{position:absolute;top:50%;margin-top:-.5rem}.p-fluid .p-treeselect{display:flex}.p-treeselect-clear-icon{position:absolute;top:50%;margin-top:-.5rem;cursor:pointer}.p-treeselect-clearable{position:relative}}\n"] }]
|
||
|
}], ctorParameters: () => [{ type: i1.PrimeNGConfig }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i1.OverlayService }], propDecorators: { inputId: [{
|
||
|
type: Input
|
||
|
}], scrollHeight: [{
|
||
|
type: Input
|
||
|
}], disabled: [{
|
||
|
type: Input,
|
||
|
args: [{ transform: booleanAttribute }]
|
||
|
}], metaKeySelection: [{
|
||
|
type: Input,
|
||
|
args: [{ transform: booleanAttribute }]
|
||
|
}], variant: [{
|
||
|
type: Input
|
||
|
}], display: [{
|
||
|
type: Input
|
||
|
}], selectionMode: [{
|
||
|
type: Input
|
||
|
}], tabindex: [{
|
||
|
type: Input
|
||
|
}], ariaLabel: [{
|
||
|
type: Input
|
||
|
}], ariaLabelledBy: [{
|
||
|
type: Input
|
||
|
}], placeholder: [{
|
||
|
type: Input
|
||
|
}], panelClass: [{
|
||
|
type: Input
|
||
|
}], panelStyle: [{
|
||
|
type: Input
|
||
|
}], panelStyleClass: [{
|
||
|
type: Input
|
||
|
}], containerStyle: [{
|
||
|
type: Input
|
||
|
}], containerStyleClass: [{
|
||
|
type: Input
|
||
|
}], labelStyle: [{
|
||
|
type: Input
|
||
|
}], labelStyleClass: [{
|
||
|
type: Input
|
||
|
}], overlayOptions: [{
|
||
|
type: Input
|
||
|
}], emptyMessage: [{
|
||
|
type: Input
|
||
|
}], appendTo: [{
|
||
|
type: Input
|
||
|
}], filter: [{
|
||
|
type: Input,
|
||
|
args: [{ transform: booleanAttribute }]
|
||
|
}], filterBy: [{
|
||
|
type: Input
|
||
|
}], filterMode: [{
|
||
|
type: Input
|
||
|
}], filterPlaceholder: [{
|
||
|
type: Input
|
||
|
}], filterLocale: [{
|
||
|
type: Input
|
||
|
}], filterInputAutoFocus: [{
|
||
|
type: Input,
|
||
|
args: [{ transform: booleanAttribute }]
|
||
|
}], propagateSelectionDown: [{
|
||
|
type: Input,
|
||
|
args: [{ transform: booleanAttribute }]
|
||
|
}], propagateSelectionUp: [{
|
||
|
type: Input,
|
||
|
args: [{ transform: booleanAttribute }]
|
||
|
}], showClear: [{
|
||
|
type: Input,
|
||
|
args: [{ transform: booleanAttribute }]
|
||
|
}], resetFilterOnHide: [{
|
||
|
type: Input,
|
||
|
args: [{ transform: booleanAttribute }]
|
||
|
}], virtualScroll: [{
|
||
|
type: Input
|
||
|
}], virtualScrollItemSize: [{
|
||
|
type: Input
|
||
|
}], virtualScrollOptions: [{
|
||
|
type: Input
|
||
|
}], autofocus: [{
|
||
|
type: Input,
|
||
|
args: [{ transform: booleanAttribute }]
|
||
|
}], options: [{
|
||
|
type: Input
|
||
|
}], showTransitionOptions: [{
|
||
|
type: Input
|
||
|
}], hideTransitionOptions: [{
|
||
|
type: Input
|
||
|
}], onNodeExpand: [{
|
||
|
type: Output
|
||
|
}], onNodeCollapse: [{
|
||
|
type: Output
|
||
|
}], onShow: [{
|
||
|
type: Output
|
||
|
}], onHide: [{
|
||
|
type: Output
|
||
|
}], onClear: [{
|
||
|
type: Output
|
||
|
}], onFilter: [{
|
||
|
type: Output
|
||
|
}], onNodeUnselect: [{
|
||
|
type: Output
|
||
|
}], onNodeSelect: [{
|
||
|
type: Output
|
||
|
}], templates: [{
|
||
|
type: ContentChildren,
|
||
|
args: [PrimeTemplate]
|
||
|
}], containerEl: [{
|
||
|
type: ViewChild,
|
||
|
args: ['container']
|
||
|
}], focusInput: [{
|
||
|
type: ViewChild,
|
||
|
args: ['focusInput']
|
||
|
}], filterViewChild: [{
|
||
|
type: ViewChild,
|
||
|
args: ['filter']
|
||
|
}], treeViewChild: [{
|
||
|
type: ViewChild,
|
||
|
args: ['tree']
|
||
|
}], panelEl: [{
|
||
|
type: ViewChild,
|
||
|
args: ['panel']
|
||
|
}], overlayViewChild: [{
|
||
|
type: ViewChild,
|
||
|
args: ['overlay']
|
||
|
}], firstHiddenFocusableElementOnOverlay: [{
|
||
|
type: ViewChild,
|
||
|
args: ['firstHiddenFocusableEl']
|
||
|
}], lastHiddenFocusableElementOnOverlay: [{
|
||
|
type: ViewChild,
|
||
|
args: ['lastHiddenFocusableEl']
|
||
|
}] } });
|
||
|
export class TreeSelectModule {
|
||
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: TreeSelectModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
||
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.7", ngImport: i0, type: TreeSelectModule, declarations: [TreeSelect], imports: [CommonModule, OverlayModule, RippleModule, SharedModule, TreeModule, AutoFocusModule, SearchIcon, TimesIcon, ChevronDownIcon], exports: [TreeSelect, OverlayModule, SharedModule, TreeModule] });
|
||
|
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: TreeSelectModule, imports: [CommonModule, OverlayModule, RippleModule, SharedModule, TreeModule, AutoFocusModule, SearchIcon, TimesIcon, ChevronDownIcon, OverlayModule, SharedModule, TreeModule] });
|
||
|
}
|
||
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: TreeSelectModule, decorators: [{
|
||
|
type: NgModule,
|
||
|
args: [{
|
||
|
imports: [CommonModule, OverlayModule, RippleModule, SharedModule, TreeModule, AutoFocusModule, SearchIcon, TimesIcon, ChevronDownIcon],
|
||
|
exports: [TreeSelect, OverlayModule, SharedModule, TreeModule],
|
||
|
declarations: [TreeSelect]
|
||
|
}]
|
||
|
}] });
|
||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJlZXNlbGVjdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hcHAvY29tcG9uZW50cy90cmVlc2VsZWN0L3RyZWVzZWxlY3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFFSCxnQkFBZ0IsRUFDaEIsdUJBQXVCLEVBRXZCLFNBQVMsRUFDVCxlQUFlLEVBRWYsWUFBWSxFQUNaLFVBQVUsRUFDVixLQUFLLEVBQ0wsUUFBUSxFQUNSLE1BQU0sRUFHTixTQUFTLEVBQ1QsaUJBQWlCLEVBQ3BCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ25ELE9BQU8sRUFBaUQsYUFBYSxFQUFtQixZQUFZLEVBQVksTUFBTSxhQUFhLENBQUM7QUFDcEksT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN6QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDNUQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNoRCxPQUFPLEVBQVcsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDekQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlDLE9BQU8sRUFBeUIsVUFBVSxFQUE4QyxNQUFNLGNBQWMsQ0FBQztBQUM3RyxPQUFPLEVBQUUsV0FBVyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRS9ELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQzs7Ozs7OztBQUdwRCxNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBUTtJQUMxQyxPQUFPLEVBQUUsaUJBQWlCO0lBQzFCLFdBQVcs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
|