UNPKG

@progress/kendo-angular-treelist

Version:

Kendo UI TreeList for Angular - Display hierarchical data in an Angular tree grid view that supports sorting, filtering, paging, and much more.

1,264 lines (1,249 loc) 1.04 MB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ import * as i0 from '@angular/core'; import { Directive, Optional, EventEmitter, Injectable, QueryList, Input, ContentChildren, ContentChild, InjectionToken, forwardRef, Component, SkipSelf, Host, isDevMode, SecurityContext, Inject, Output, HostBinding, Pipe, ViewChild, ViewChildren, Self, HostListener, NgZone, TemplateRef, ChangeDetectionStrategy, ViewEncapsulation, NgModule } from '@angular/core'; import * as i1$4 from '@progress/kendo-angular-common'; import { isDocumentAvailable, isPresent as isPresent$1, hasClasses as hasClasses$1, Keys, normalizeNumpadKeys, anyChanged, isChanged as isChanged$1, ResizeSensorComponent, EventsOutsideAngularDirective, KendoInput, replaceMessagePlaceholder, guid, DraggableDirective, TemplateContextDirective, hasObservers, ResizeBatchService } from '@progress/kendo-angular-common'; import * as i2 from '@progress/kendo-angular-icons'; import { IconWrapperComponent, IconsService, KENDO_ICONS } from '@progress/kendo-angular-icons'; import { DatePickerComponent, DatePickerCustomMessagesComponent, CalendarDOMService, CenturyViewService, DecadeViewService, MonthViewService, YearViewService, NavigationService as NavigationService$1 } from '@progress/kendo-angular-dateinputs'; import * as i1 from '@progress/kendo-angular-popup'; import { PopupService } from '@progress/kendo-angular-popup'; import { DialogContainerService, DialogService, WindowService, WindowContainerService } from '@progress/kendo-angular-dialog'; import { NgSwitch, NgSwitchCase, NgIf, NgFor, NgTemplateOutlet, NgSwitchDefault, NgClass, NgStyle } from '@angular/common'; import * as i4 from '@angular/forms'; import { ReactiveFormsModule, NG_VALUE_ACCESSOR, FormsModule, FormControl, FormGroup } from '@angular/forms'; import { merge, of, fromEvent, isObservable, BehaviorSubject, Subscription, Subject, zip as zip$1, from, interval, Observable } from 'rxjs'; import { auditTime, take, switchMap, map, distinctUntilChanged, filter, tap, throttleTime, skip, takeUntil, switchMapTo, bufferCount, delay, debounceTime } from 'rxjs/operators'; import { validatePackage } from '@progress/kendo-licensing'; import * as i1$1 from '@progress/kendo-angular-l10n'; import { ComponentMessages, LocalizationService, L10N_PREFIX } from '@progress/kendo-angular-l10n'; import { DragTargetContainerDirective, DropTargetContainerDirective } from '@progress/kendo-angular-utils'; import { orderBy, isCompositeFilterDescriptor, process, aggregateBy } from '@progress/kendo-data-query'; import * as i1$2 from '@angular/platform-browser'; import { plusIcon, cancelIcon, lockIcon, unlockIcon, insertMiddleIcon, caretAltDownIcon, caretAltRightIcon, caretAltLeftIcon, reorderIcon, filterClearIcon, filterIcon, chevronUpIcon, chevronDownIcon, columnsIcon, sortAscSmallIcon, sortDescSmallIcon, displayInlineFlexIcon, maxWidthIcon, moreVerticalIcon, fileExcelIcon, filePdfIcon } from '@progress/kendo-svg-icons'; import * as i107 from '@progress/kendo-angular-pager'; import { PagerContextService, PagerNavigationService, PagerTemplateDirective, KENDO_PAGER } from '@progress/kendo-angular-pager'; import { getter, setter } from '@progress/kendo-common'; import * as i1$6 from '@progress/kendo-angular-inputs'; import { NumericTextBoxComponent, CheckBoxComponent, TextBoxComponent, NumericTextBoxCustomMessagesComponent, RadioButtonComponent } from '@progress/kendo-angular-inputs'; import * as i1$3 from '@progress/kendo-angular-intl'; import * as i1$5 from '@progress/kendo-angular-dropdowns'; import { DropDownListComponent, AutoCompleteComponent } from '@progress/kendo-angular-dropdowns'; import { ButtonComponent, Button } from '@progress/kendo-angular-buttons'; import { trigger, state, style, transition, animate } from '@angular/animations'; import { saveAs } from '@progress/kendo-file-saver'; import * as i100 from '@progress/kendo-angular-excel-export'; import { workbookOptions, toDataURL, ColumnBase as ColumnBase$1, ColumnComponent as ColumnComponent$1, ColumnGroupComponent as ColumnGroupComponent$1, FooterTemplateDirective as FooterTemplateDirective$1, GroupFooterTemplateDirective, GroupHeaderColumnTemplateDirective, GroupHeaderTemplateDirective } from '@progress/kendo-angular-excel-export'; import * as i106 from '@progress/kendo-angular-toolbar'; import { KENDO_TOOLBAR } from '@progress/kendo-angular-toolbar'; import { PDFExportMarginComponent, PDFExportTemplateDirective, PDFExportComponent } from '@progress/kendo-angular-pdf-export'; /** * @hidden */ const packageMetadata = { name: '@progress/kendo-angular-treelist', productName: 'Kendo UI for Angular', productCode: 'KENDOUIANGULAR', productCodes: ['KENDOUIANGULAR'], publishDate: 1756992973, version: '20.0.3', licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/' }; /** * Represents the column cell template of the TreeList ([more information and example]({% slug templates_columns_treelist %}#toc-cell-template)). * Use this directive to customize the content of the cells. To define the cell template, nest an `<ng-template>` tag with the `kendoTreeListCellTemplate` directive inside a `<kendo-treelist-column>` tag. * * The template context is set to the current data item and provides the following fields: * - `columnIndex`&mdash;The current column index. Use as an alias for a template variable with `let-columnIndex="columnIndex"`. * - `column`&mdash;The current column instance. Use as an alias for a template variable with `let-column="column"`. * - `dataItem`&mdash;The current data item. Represents the default context for any template variable using `let-x` syntax, for example, `let-dataItem`. * - `cellContext`&mdash;An object for passing context information to built-in directives. * - `hasChildren`&mdash;Specifies if the item has children. * - `isExpanded`&mdash;Specifies if the item is expanded. * - `level`&mdash;The hierarchy level of the item. * - `loading`&mdash;Specifies if the item children are currently loading. * - `rowIndex`&mdash;The current row index. Use it as an alias for a template variable with `let-rowIndex="rowIndex"`. * * @example * ```html * <kendo-treelist ...> * <kendo-treelist-column field="ProductName"> * <ng-template kendoTreeListCellTemplate let-dataItem let-rowIndex="rowIndex" let-column="column"> * Data Row: {{rowIndex}} * </ng-template> * </kendo-treelist-column> * </kendo-treelist> * ``` */ class CellTemplateDirective { templateRef; constructor(templateRef) { this.templateRef = templateRef; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: CellTemplateDirective, isStandalone: true, selector: "[kendoTreeListCellTemplate]", ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellTemplateDirective, decorators: [{ type: Directive, args: [{ selector: '[kendoTreeListCellTemplate]', standalone: true }] }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{ type: Optional }] }]; } }); /** * Represents the column edit-cell template of the TreeList ([see example](slug:editing_template_forms_treelist)). Use this directive to customize the content of edited cells. To define the cell template, nest an `<ng-template>` tag with the `kendoTreeListEditTemplate` directive inside a `<kendo-treelist-column>` tag. * * The template context contains the following fields: * - `column`&mdash;The current column instance. * - `dataItem`&mdash;The current data item. * - `cellContext`&mdash;An object used to pass context information to built-in directives. * - `formGroup`&mdash;The current [`FormGroup`](link:site.data.urls.angular['formgroupapi']). If you use the TreeList inside [Template-Driven Forms](link:site.data.urls.angular['forms']), `formGroup` is `undefined`. * - `isNew`&mdash;The state of the current item. * - `rowIndex`&mdash;The current row index. If inside a new item row, `rowIndex` is `-1`. * * @example * ```html * <kendo-treelist ...> * <kendo-treelist-command-column title="command"> * <ng-template kendoTreeListEditTemplate let-rowIndex="rowIndex"> * {{rowIndex}} * </ng-template> * </kendo-treelist-command-column> * </kendo-treelist> * ``` */ class EditTemplateDirective { templateRef; constructor(templateRef) { this.templateRef = templateRef; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: EditTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: EditTemplateDirective, isStandalone: true, selector: "[kendoTreeListEditTemplate]", ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: EditTemplateDirective, decorators: [{ type: Directive, args: [{ selector: '[kendoTreeListEditTemplate]', standalone: true }] }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{ type: Optional }] }]; } }); /** * Represents the template for the column menu in the TreeList. Use this directive to customize the content of the column menu for all or specific columns. * To define the content template, nest an `<ng-template>` tag with the `kendoTreeListColumnMenuTemplate` directive inside the `kendo-treelist` or the `<kendo-treelist-column>` component. * * The template context is passed through the following fields: * - `service`&mdash;Represents the [ColumnMenuService]({% slug api_treelist_columnmenuservice %}). * - `column`&mdash;Represents the TreeList column. * * @example * ```html * <kendo-treelist ... > * <ng-template kendoTreeListColumnMenuTemplate let-service="service"> * <kendo-treelist-columnmenu-sort [service]="service"> * </kendo-treelist-columnmenu-sort> * </ng-template> * <kendo-treelist-column field="name"> * <ng-template kendoTreeListColumnMenuTemplate let-service="service"> * <kendo-treelist-columnmenu-sort [service]="service"> * </kendo-treelist-columnmenu-sort> * </ng-template> * </kendo-treelist-column> * </kendo-treelist> * ``` */ class ColumnMenuTemplateDirective { templateRef; constructor(templateRef) { this.templateRef = templateRef; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColumnMenuTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: ColumnMenuTemplateDirective, isStandalone: true, selector: "[kendoTreeListColumnMenuTemplate]", ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColumnMenuTemplateDirective, decorators: [{ type: Directive, args: [{ selector: '[kendoTreeListColumnMenuTemplate]', standalone: true }] }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{ type: Optional }] }]; } }); /** * @hidden */ class OptionChangesService { columns = new EventEmitter(); options = new EventEmitter(); optionChanged() { this.options.emit(); } columnChanged() { this.columns.emit(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OptionChangesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OptionChangesService }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OptionChangesService, decorators: [{ type: Injectable }] }); /** * Represents the column footer cell template of the TreeList ([more information and example]({% slug templates_columns_treelist %}#toc-footer-template)). * Use this directive to customize the table footer cell for the column. * To define a footer template, nest an `<ng-template>` tag with the `kendoTreeListFooterTemplate` directive inside the `<kendo-treelist-column>` tag. * * The template context is set to the aggregate values and provides the following fields: * - `aggregates`&mdash;The aggregates for the level items. * - `column`&mdash;Defines an instance of the [`ColumnComponent`]({% slug api_treelist_columncomponent %}) option. * - `columnIndex`&mdash;Defines the current column index. * - `field`&mdash;The name of the column field, if set. * - `items`&mdash;The data items on this level. * - `parentItem`&mdash;The parent data item; `null` for root level items. * * @example * ```html * <kendo-treelist-column field="name"> * <ng-template kendoTreeListFooterTemplate let-aggregates="aggregates"> * {{ aggregates.name.count }} * </ng-template> * </kendo-treelist-column> * ``` */ class FooterTemplateDirective { templateRef; constructor(templateRef) { this.templateRef = templateRef; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FooterTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: FooterTemplateDirective, isStandalone: true, selector: "[kendoTreeListFooterTemplate]", ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FooterTemplateDirective, decorators: [{ type: Directive, args: [{ selector: '[kendoTreeListFooterTemplate]', standalone: true }] }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{ type: Optional }] }]; } }); /** * Represents the column header cell template of the TreeList * ([more information and example]({% slug templates_columns_treelist %}#toc-header-template)). * Use this directive to customize the table header cell for the column. * To define a header template, nest an `<ng-template>` tag with the * [`kendoTreeListHeaderTemplate`]({% slug api_treelist_headertemplatedirective %}) directive inside the `<kendo-treelist-column>` tag. * * The template context is set to the current column and provides the following fields: * - `column`&mdash;Defines an instance of the [`ColumnComponent`]({% slug api_treelist_columncomponent %}) option. * - `columnIndex`&mdash;Defines the current column index. * * @example * ```html * <kendo-treelist-column field="name"> * <ng-template * kendoTreeListHeaderTemplate * let-column> * {{ column.field }} * </ng-template> * </kendo-treelist-column> * ``` */ class HeaderTemplateDirective { templateRef; constructor(templateRef) { this.templateRef = templateRef; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HeaderTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: HeaderTemplateDirective, isStandalone: true, selector: "[kendoTreeListHeaderTemplate]", ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HeaderTemplateDirective, decorators: [{ type: Directive, args: [{ selector: '[kendoTreeListHeaderTemplate]', standalone: true }] }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{ type: Optional }] }]; } }); let columnId = 0; /** * @hidden */ const isSpanColumn = column => column.isSpanColumn; /** * @hidden */ const isCheckboxColumn = column => column.isCheckboxColumn; /** * @hidden */ const isRowReorderColumn = column => column.isRowReorderColumn; const isColumnContainer = column => column.isColumnGroup || isSpanColumn(column); /** * Serves as the base class for column components in the TreeList. */ class ColumnBase { parent; optionChanges; /** * @hidden */ matchesMedia = true; /** * The column index after reordering. * The orderIndex` is a read-only property. Setting this field does not affect column order. * @default 0 */ orderIndex = 0; /** * @hidden */ set leafIndex(value) { this._leafIndex = value; } /** * @hidden */ get leafIndex() { return this._leafIndex; } _leafIndex; /** * @hidden */ isColumnGroup = false; /** * @hidden */ isSpanColumn = false; /** * @hidden */ get id() { return this._id; } /** * Indicates whether the column is resizable. * @default true */ resizable = true; /** * Indicates whether the column is reorderable. * @default true */ reorderable = true; /** * Sets the minimum width (in pixels) for resizing the column using the UI. * @default 10 */ minResizableWidth = 10; /** * Sets the title of the column. */ title; /** * Sets the width of the column (in pixels). */ set width(value) { this._width = parseInt(value, 10); } get width() { return this._width; } /** * Indicates whether the column is automatically resized during initialization to fit its header and row content. */ autoSize; /** * Toggles the locked (frozen) state of the columns ([more information and example](slug:locked_columns_treelist)). * @default false */ set locked(value) { this._locked = value; } get locked() { return this._locked; } _locked = false; /** * Sets the visibility of the column ([see example](slug:hidden_columns_treelist#toc-using-the-built-in-options)). * @default false */ hidden; /** * Sets the condition that must be satisfied for a column to remain visible ([see example](slug:responsive_treelist#toc-columns)). * If you set the `hidden` property, the behavior of `media` is overridden. */ media; /** * Specifies if the column can be locked or unlocked from the column menu or by reordering the columns. * @default true */ lockable = true; /** * Specifies if the column menu is shown for the column. * @default true */ columnMenu = true; /** * Specifies if the column is included in the column-chooser list. * @default true */ includeInChooser = true; /** * Sets the `role` attribute for the table cells (excluding the footer and header) of the column. * @default "gridcell" */ tableCellsRole = 'gridcell'; /** * Sets custom styles for the table cells (excluding the footer and header) of the column. Uses the [`NgStyle`](link:site.data.urls.angular['ngstyleapi']) directive. [See example](slug:styling_treelist_columns). */ style; /** * Sets custom styles for the header cell of the column. Uses the [`NgStyle`](link:site.data.urls.angular['ngstyleapi']) directive. [See example.](slug:styling_treelist_columns) */ headerStyle; /** * Sets custom styles for the footer cell of the column. Uses the [`NgStyle`](link:site.data.urls.angular['ngstyleapi']) directive. [See example.](slug:styling_treelist_columns) */ footerStyle; /** * Sets custom CSS classes to the column cells. Uses the [`NgClass`](link:site.data.urls.angular['ngclassapi']) directive. To customize header and footer column cells, use the [`headerClass`]({% slug api_treelist_columncomponent %}#toc-headerclass) and [`footerClass`]({% slug api_treelist_columncomponent %}#toc-footerclass) inputs. */ cssClass; /** * Sets custom CSS classes to the column header cell. Uses the [`NgClass`](link:site.data.urls.angular['ngclassapi']) directive. [See example](slug:styling_treelist_columns). */ headerClass; /** * Sets the custom CSS classes to the column footer cell. Under the hood, to apply the property, * the `footerClass` option uses the * [`NgClass`](link:site.data.urls.angular['ngclassapi']) directive. [See example](slug:styling_treelist_columns). */ footerClass; /** * @hidden */ headerTemplates = new QueryList(); /** * @hidden */ footerTemplate; /** * @hidden */ columnMenuTemplates = new QueryList(); /** * @hidden */ resizeStartWidth; /** * @hidden */ get level() { if (this.parent && isSpanColumn(this.parent)) { return this.parent.level; } return this.parent ? this.parent.level + 1 : 0; } /** * @hidden */ get isLocked() { return this.parent ? this.parent.isLocked : this.locked; } _width; /** * @hidden */ get colspan() { return 1; } /** * @hidden */ rowspan(totalColumnLevels) { return this.level < totalColumnLevels ? (totalColumnLevels - this.level) + 1 : 1; } /** * @hidden */ get headerTemplateRef() { const template = this.headerTemplates.first; return template ? template.templateRef : undefined; } /** * @hidden */ get footerTemplateRef() { return this.footerTemplate ? this.footerTemplate.templateRef : undefined; } /** * @hidden */ get columnMenuTemplateRef() { const template = this.columnMenuTemplates.first; return template ? template.templateRef : null; } /** * @hidden */ get displayTitle() { return this.title; } /** * @hidden */ get isVisible() { return !this.hidden && this.matchesMedia; } /** * @hidden */ get isEditable() { return false; } _id; /** * @hidden */ constructor(parent, optionChanges) { this.parent = parent; this.optionChanges = optionChanges; if (parent && !isColumnContainer(parent)) { throw new Error('Columns can be nested only inside ColumnGroupComponent'); } this._id = `k-grid-column-${columnId++}`; } ngOnChanges(_changes) { if (this.optionChanges) { this.optionChanges.columnChanged(); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColumnBase, deps: [{ token: ColumnBase }, { token: OptionChangesService }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: ColumnBase, inputs: { resizable: "resizable", reorderable: "reorderable", minResizableWidth: "minResizableWidth", title: "title", width: "width", autoSize: "autoSize", locked: "locked", hidden: "hidden", media: "media", lockable: "lockable", columnMenu: "columnMenu", includeInChooser: "includeInChooser", tableCellsRole: "tableCellsRole", style: "style", headerStyle: "headerStyle", footerStyle: "footerStyle", cssClass: ["class", "cssClass"], headerClass: "headerClass", footerClass: "footerClass" }, queries: [{ propertyName: "footerTemplate", first: true, predicate: FooterTemplateDirective, descendants: true }, { propertyName: "headerTemplates", predicate: HeaderTemplateDirective }, { propertyName: "columnMenuTemplates", predicate: ColumnMenuTemplateDirective }], usesOnChanges: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColumnBase, decorators: [{ type: Directive, args: [{}] }], ctorParameters: function () { return [{ type: ColumnBase }, { type: OptionChangesService }]; }, propDecorators: { resizable: [{ type: Input }], reorderable: [{ type: Input }], minResizableWidth: [{ type: Input }], title: [{ type: Input }], width: [{ type: Input }], autoSize: [{ type: Input }], locked: [{ type: Input }], hidden: [{ type: Input }], media: [{ type: Input }], lockable: [{ type: Input }], columnMenu: [{ type: Input }], includeInChooser: [{ type: Input }], tableCellsRole: [{ type: Input }], style: [{ type: Input }], headerStyle: [{ type: Input }], footerStyle: [{ type: Input }], cssClass: [{ type: Input, args: ['class'] }], headerClass: [{ type: Input }], footerClass: [{ type: Input }], headerTemplates: [{ type: ContentChildren, args: [HeaderTemplateDirective, { descendants: false }] }], footerTemplate: [{ type: ContentChild, args: [FooterTemplateDirective, { static: false }] }], columnMenuTemplates: [{ type: ContentChildren, args: [ColumnMenuTemplateDirective] }] } }); const EMPTY_REGEX = /^\s*$/; /** * @hidden */ const isPresent = (value) => value !== null && value !== undefined; /** * @hidden */ const isBlank = (value) => value === null || value === undefined; /** * @hidden */ const isArray = (value) => Array.isArray(value); /** * @hidden */ const isTruthy = (value) => !!value; /** * @hidden */ const isNullOrEmptyString = (value) => isBlank(value) || EMPTY_REGEX.test(value); /** * @hidden */ const observe = (list) => merge(of(list), list.changes); /** * @hidden */ const isUniversal = () => typeof document === 'undefined'; /** * @hidden */ const isString = (value) => typeof value === 'string'; /** * @hidden */ const isNumber = (value) => typeof value === "number" && !isNaN(value); /** * @hidden */ const extractFormat = (format) => { if (isString(format) && !isNullOrEmptyString(format) && format.startsWith('{0:')) { return format.slice(3, format.length - 1); } return format; }; /** * @hidden */ const not = (fn) => (...args) => !fn(...args); /** * @hidden */ const or = (...conditions) => (value) => conditions.reduce((acc, x) => acc || x(value), false); /** * @hidden */ const and = (...conditions) => (value) => conditions.reduce((acc, x) => acc && x(value), true); /** * @hidden */ const Skip = new InjectionToken("Skip"); /** * @hidden */ const createPromise = () => { let resolveFn, rejectFn; const promise = new Promise((resolve, reject) => { resolveFn = (data) => { resolve(data); return promise; }; rejectFn = (data) => { reject(data); return promise; }; }); promise.resolve = resolveFn; promise.reject = rejectFn; return promise; }; /** @hidden */ const iterator = getIterator(); // TODO: Move to kendo-common function getIterator() { if (typeof Symbol === 'function' && Symbol.iterator) { return Symbol.iterator; } const keys = Object.getOwnPropertyNames(Map.prototype); const proto = Map.prototype; for (let i = 0; i < keys.length; ++i) { const key = keys[i]; if (key !== 'entries' && key !== 'size' && proto[key] === proto.entries) { return key; } } } const FRAME_DURATION = 1000 / 60; const wnd = typeof window !== 'undefined' ? window : {}; /** @hidden */ const requestAnimationFrame = wnd.requestAnimationFrame || wnd.msRequestAnimationFrame || (callback => setTimeout(callback, FRAME_DURATION)); /** @hidden */ const cancelAnimationFrame = wnd.cancelAnimationFrame || wnd.msCancelRequestAnimationFrame || clearTimeout; /** @hidden */ const isColumnEditable = (column, formGroup) => column.isEditable !== false && (column.editTemplate || (formGroup && column.field && formGroup.get(column.field))); /** * Represents the filter-cell template for the TreeList. * Use this directive to customize the filter row cell for a column. * See [custom filter row components](slug:filter_row_treelist#toc-custom-filters). * * The template context is set to the filter descriptor and provides the following fields: * - `column`&mdash;The current column instance. Use as an alias for a template variable with `let-column="column"`. * - `filter`&mdash;The filter descriptor. * - `cellContext`&mdash;An object used to pass context information to built-in directives. * * @example * ```html * <kendo-treelist-column field="name" title="Name"> * <ng-template kendoTreeListFilterCellTemplate let-column="column" let-filter="filter" let-cellContext="cellContext"> * <kendo-maskedtextbox mask="(999) 000-0000" * [promptPlaceholder]="prompt" [includeLiterals]="true" * (valueChange)="phoneChange($event)" * > * </kendo-maskedtextbox> * </ng-template> * </kendo-treelist-column> * ``` */ class FilterCellTemplateDirective { templateRef; constructor(templateRef) { this.templateRef = templateRef; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FilterCellTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: FilterCellTemplateDirective, isStandalone: true, selector: "[kendoTreeListFilterCellTemplate]", ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FilterCellTemplateDirective, decorators: [{ type: Directive, args: [{ selector: '[kendoTreeListFilterCellTemplate]', standalone: true }] }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{ type: Optional }] }]; } }); /** * Represents the filter-menu template for the TreeList filter menu. * * Use this directive to provide a custom template for the filter menu in a TreeList column * ([see example](slug:filter_menu_treelist#toc-custom-filter-menu-components)). * * @example * ```html * <kendo-treelist-column field="title" title="Title" [width]="180"> * <ng-template kendoTreeListFilterMenuTemplate * let-filter="filter" * let-filterService="filterService"> * <my-custom-filter-menu-component * [currentFilter]="filter" * [filterService]="filterService"> * </my-custom-filter-menu-component> * </ng-template> * </kendo-treelist-column> * ``` */ class FilterMenuTemplateDirective { templateRef; constructor(templateRef) { this.templateRef = templateRef; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FilterMenuTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: FilterMenuTemplateDirective, isStandalone: true, selector: "[kendoTreeListFilterMenuTemplate]", ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FilterMenuTemplateDirective, decorators: [{ type: Directive, args: [{ selector: '[kendoTreeListFilterMenuTemplate]', standalone: true }] }], ctorParameters: function () { return [{ type: i0.TemplateRef, decorators: [{ type: Optional }] }]; } }); /** * @hidden */ function isColumnComponent(column) { return isPresent(column.field); } /** * Represents a column in the TreeList. Use this component to define a data-bound column. * * @example * ```html * <kendo-treelist [kendoTreeListFlatBinding]="data" ...> * <kendo-treelist-column field="name" title="Name"></kendo-treelist-column> * <kendo-treelist-column field="title" title="Title"></kendo-treelist-column> * </kendo-treelist> * ``` * @remarks * Supported children components are: * {@link StringFilterCellComponent}, * {@link NumericFilterCellComponent}, * {@link BooleanFilterCellComponent}, * {@link DateFilterCellComponent}, * {@link StringFilterMenuComponent}, * {@link NumericFilterMenuComponent}, * {@link BooleanFilterMenuComponent}, * {@link DateFilterMenuComponent}, * {@link FilterCellOperatorsComponent}. */ class ColumnComponent extends ColumnBase { /** * Specifies if the expanded indicator appears in the column. */ expandable; /** * Sets the field to which the column is bound. */ field; /** * Sets the format applied to the value before display. For supported date and number formats, see the [Column Formats](slug:formats_columns_treelist) article. */ format; /** * Allows the column headers to be clicked and the `sortChange` event emitted. You must handle the `sortChange` event and sort the data. * @default true */ sortable = true; /** * Sets the editor type ([see example]({% slug editing_reactive_forms_treelist %}#toc-setup)). Used when the column enters edit mode. [See example](slug:editing_reactive_forms_treelist). * @default 'text' */ editor = 'text'; /** * Sets the filter type displayed inside the filter row. * @default 'text' */ filter = 'text'; /** * Specifies if a filter UI appears for this column. * @default true */ filterable = true; /** * Specifies if the column is editable. * @default true */ editable = true; template; editTemplate; filterCellTemplate; filterMenuTemplate; constructor(parent, optionChanges) { super(parent, optionChanges); } get templateRef() { return this.template ? this.template.templateRef : undefined; } get editTemplateRef() { return this.editTemplate ? this.editTemplate.templateRef : undefined; } get filterCellTemplateRef() { return this.filterCellTemplate ? this.filterCellTemplate.templateRef : undefined; } get filterMenuTemplateRef() { return this.filterMenuTemplate ? this.filterMenuTemplate.templateRef : undefined; } get displayTitle() { return this.title === undefined ? this.field : this.title; } /** * @hidden */ get isEditable() { return this.editable !== false; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColumnComponent, deps: [{ token: ColumnBase, host: true, optional: true, skipSelf: true }, { token: OptionChangesService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ColumnComponent, isStandalone: true, selector: "kendo-treelist-column", inputs: { expandable: "expandable", field: "field", format: "format", sortable: "sortable", editor: "editor", filter: "filter", filterable: "filterable", editable: "editable" }, providers: [ { provide: ColumnBase, useExisting: forwardRef(() => ColumnComponent) } ], queries: [{ propertyName: "template", first: true, predicate: CellTemplateDirective, descendants: true }, { propertyName: "editTemplate", first: true, predicate: EditTemplateDirective, descendants: true }, { propertyName: "filterCellTemplate", first: true, predicate: FilterCellTemplateDirective, descendants: true }, { propertyName: "filterMenuTemplate", first: true, predicate: FilterMenuTemplateDirective, descendants: true }], usesInheritance: true, ngImport: i0, template: ``, isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColumnComponent, decorators: [{ type: Component, args: [{ providers: [ { provide: ColumnBase, useExisting: forwardRef(() => ColumnComponent) } ], selector: 'kendo-treelist-column', template: ``, standalone: true }] }], ctorParameters: function () { return [{ type: ColumnBase, decorators: [{ type: SkipSelf }, { type: Host }, { type: Optional }] }, { type: OptionChangesService }]; }, propDecorators: { expandable: [{ type: Input }], field: [{ type: Input }], format: [{ type: Input }], sortable: [{ type: Input }], editor: [{ type: Input }], filter: [{ type: Input }], filterable: [{ type: Input }], editable: [{ type: Input }], template: [{ type: ContentChild, args: [CellTemplateDirective, { static: false }] }], editTemplate: [{ type: ContentChild, args: [EditTemplateDirective, { static: false }] }], filterCellTemplate: [{ type: ContentChild, args: [FilterCellTemplateDirective, { static: false }] }], filterMenuTemplate: [{ type: ContentChild, args: [FilterMenuTemplateDirective, { static: false }] }] } }); /** * @hidden */ function isSpanColumnComponent(column) { return column.isSpanColumn; } /** * Represents a column that spans multiple data cells while keeping individual header and footer cells. * Use this component to create flexible layouts and retain built-in UI for [sorting]({% slug sorting_treelist %}) and [filtering]({% slug filtering_treelist %}). * Wrap the columns to merge inside the `<kendo-treelist-span-column>` tag. * * @example * ```html * <kendo-treelist-span-column> * <kendo-treelist-column field="field1"></kendo-treelist-column> * <kendo-treelist-column field="field2"></kendo-treelist-column> * <ng-template kendoTreeListCellTemplate let-dataItem> * <h5>{{ dataItem.field1 }}</h5> * <p>{{ dataItem.field2 }}</p> * </ng-template> * </kendo-treelist-span-column> * ``` */ class SpanColumnComponent extends ColumnBase { /** * Specifies if the expanded indicator appears in the column. */ expandable; /* * @hidden */ isSpanColumn = true; /** * @hidden */ title; /** * @hidden */ headerClass; /** * @hidden */ footerClass; /** * @hidden */ headerStyle; /** * @hidden */ footerStyle; template = new QueryList(); editTemplate = new QueryList(); /** * @hidden */ childColumns = new QueryList(); /** * @hidden */ includeInChooser = false; /** * Defines whether the edit template of the column is rendered. * To enable editing for a spanned column, set an edit template for it. * @default false */ set editable(value) { this._editable = value; } get editable() { return isPresent(this.editTemplateRef) && this._editable; } /** * @hidden * added for backwards compitability */ set width(_value) { } get width() { return this.childColumns.reduce((total, column) => total + column.width, 0); } /** * @hidden */ get leafIndex() { return this.childColumns.first.leafIndex; } _editable = true; constructor(parent, optionChanges) { super(parent, optionChanges); if (parent && parent.isSpanColumn) { throw new Error('SpanColumn cannot be nested inside another SpanColumn'); } } /** * @hidden */ get templateRef() { const template = this.template.first; return template ? template.templateRef : undefined; } /** * @hidden */ get editTemplateRef() { const editTemplate = this.editTemplate.first; return editTemplate ? editTemplate.templateRef : undefined; } /** * @hidden */ get colspan() { return this.childColumns.filter(c => c.isVisible).length; } /** * Toggles the locked (frozen) state of the columns. Locked columns are visible at all times during horizontal scrolling. [See example](slug:locked_columns_treelist). * @default false */ set locked(value) { this._locked = value; } get locked() { return this._locked || this.childColumns.some(c => c.locked); } get isEditable() { return Boolean(this.editTemplateRef); } get childrenArray() { return this.childColumns.toArray(); } get hasChildren() { return this.childColumns.length > 0; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SpanColumnComponent, deps: [{ token: ColumnBase, host: true, optional: true, skipSelf: true }, { token: OptionChangesService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SpanColumnComponent, isStandalone: true, selector: "kendo-treelist-span-column", inputs: { expandable: "expandable", title: "title", headerClass: "headerClass", footerClass: "footerClass", headerStyle: "headerStyle", footerStyle: "footerStyle", editable: "editable", locked: "locked" }, providers: [ { provide: ColumnBase, useExisting: forwardRef(() => SpanColumnComponent) } ], queries: [{ propertyName: "template", predicate: CellTemplateDirective }, { propertyName: "editTemplate", predicate: EditTemplateDirective }, { propertyName: "childColumns", predicate: ColumnComponent }], usesInheritance: true, ngImport: i0, template: ``, isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SpanColumnComponent, decorators: [{ type: Component, args: [{ providers: [ { provide: ColumnBase, useExisting: forwardRef(() => SpanColumnComponent) } ], selector: 'kendo-treelist-span-column', template: ``, standalone: true }] }], ctorParameters: function () { return [{ type: ColumnBase, decorators: [{ type: SkipSelf }, { type: Host }, { type: Optional }] }, { type: OptionChangesService }]; }, propDecorators: { expandable: [{ type: Input }], title: [{ type: Input }], headerClass: [{ type: Input }], footerClass: [{ type: Input }], headerStyle: [{ type: Input }], footerStyle: [{ type: Input }], template: [{ type: ContentChildren, args: [CellTemplateDirective, { descendants: false }] }], editTemplate: [{ type: ContentChildren, args: [EditTemplateDirective, { descendants: false }] }], childColumns: [{ type: ContentChildren, args: [ColumnComponent] }], editable: [{ type: Input }], locked: [{ type: Input }] } }); /** * @hidden */ const expandColumns = (columns) => (columns.reduce((acc, column) => acc.concat(isSpanColumnComponent(column) ? column.childrenArray : [column]), [])); /** * @hidden */ const expandColumnsWithSpan = (columns) => (columns.reduce((acc, column) => acc.concat(isSpanColumnComponent(column) ? [column].concat(column.childrenArray) : [column]), [])); /** * @hidden */ const columnsToRender = (columns) => (expandColumns(columns).filter(x => x.isVisible)); const sumProp = (prop) => (array) => (array || []).reduce((prev, curr) => prev + (curr[prop] || 0), 0); /** * @hidden */ const sumColumnWidths = sumProp('width'); /** * @hidden */ const columnsSpan = sumProp('colspan'); const validField = new RegExp(`^[$A-Z\_a-z][$A-Z\_a-z0-9\\.]*$`); /** * @hidden */ const isValidFieldName = (fieldName) => !isNullOrEmptyString(fieldName) && validField.test(fieldName) && fieldName[0] !== "." && fieldName[fieldName.length - 1] !== "."; /** * @hidden */ const children = column => column.children.filter(child => child !== column); /** * @hidden */ const leafColumns = columns => { return columns.reduce((acc, column) => { if (column.isColumnGroup) { acc = acc.concat(leafColumns(children(column))); } else if (column.isSpanColumn) { acc = acc.concat(column.childrenArray); } else { acc.push(column); } return acc; }, []).filter(x => x.isVisible); }; /** * @hidden */ const someLeafColumn = (callback, ...columns) => leafColumns(columns).some(callback); /** * @hidden */ const resizableColumns = columns => columns.filter(column => isTruthy(column.resizable) && column.isVisible); /** * @hidden */ const sortColumns = (columns) => orderBy(columns, [{ field: 'orderIndex', dir: 'asc' }]); /** * @hidden */ const isInSpanColumn$1 = (column) => isTruthy(column.parent) && isSpanColumnComponent(column.parent); /** * @hidden */ function isColumnGroupComponent(column) { return column.isColumnGroup; } /** * Represents the column group header of the TreeList. ([More information and examples]({% slug multicolumnheaders_columns_treelist %})). * * @example * ```html * <kendo-treelist ...> * <kendo-treelist-column-group title="File Info"> * <kendo-treelist-column field="type" title="Type"> </kendo-treelist-column> * <kendo-treelist-column field="size" title="Size"> </kendo-treelist-column> * </kendo-treelist-column-group> * </kendo-treelist> * ``` */ class ColumnGroupComponent extends ColumnBase { /** * @hidden */ includeInChooser = false; /** * @hidden */ isColumnGroup = true; /** * @hidden */ minResizableWidth = 10; /** * @hidden */ children; constructor(parent, optionChanges) { super(parent, optionChanges); if (parent && parent.isSpanColumn) { throw new Error('ColumnGroupComponent cannot be nested inside SpanColumnComponent'); } } /** * @hidden */ rowspan() { return 1; } /** * @hidden */ get colspan() { if (!this.children) { return 1; } return columnsSpan(this.children .filter(child => child !== this && child.isVisible)); } /** * @hidden */ get leafIndex() { return this.children ? (this.firstChild || {}).leafIndex : -1; } get childrenArray() { return this.children.filter(c => c !== this); } get hasChildren() { return Boolean(this.firstChild); } get firstChild() { return this.children.find(column => column !== this); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColumnGroupComponent, deps: [{ token: ColumnBase, host: true, optional: true, skipSelf: true }, { token: OptionChangesService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ColumnGroupComponent, isStandalone: true, selector: "kendo-treelist-column-group", providers: [ { provide: ColumnBase, useExisting: forwardRef(() => ColumnGroupComponent) } ], queries: [{ propertyName: "children", predicate: ColumnBase }], usesInheritance: true, ngImport: i0, template: ``, isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "