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.

888 lines 52.3 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Component, ChangeDetectorRef, HostBinding, Input, QueryList, ViewChildren, TemplateRef } from '@angular/core'; import { NgFor, NgIf, NgClass, NgStyle } from '@angular/common'; import { Subscription, of, merge } from "rxjs"; import { filter, map, switchMap, tap, takeUntil } from 'rxjs/operators'; import { LocalizationService } from '@progress/kendo-angular-l10n'; import { Keys, DraggableDirective, TemplateContextDirective } from '@progress/kendo-angular-common'; import { IconWrapperComponent } from '@progress/kendo-angular-icons'; import { sortAscSmallIcon, sortDescSmallIcon } from '@progress/kendo-svg-icons'; import { isColumnComponent } from '../../columns/column.component'; import { isColumnGroupComponent } from '../../columns/column-group.component'; import { isCheckboxColumn } from '../../columns/column-base'; import { normalize } from '../../columns/sort-settings'; import { and, isNullOrEmptyString, isPresent, isTruthy, not, observe } from '../../utils'; import { columnsToRender, sortColumns, isInSpanColumn } from "../../columns/column-common"; import { SinglePopupService } from '../../common/single-popup.service'; import { hasFilterMenu, hasFilterRow } from '../../filtering/filterable'; import { DropTargetDirective } from '../../dragdrop/drop-target.directive'; import { DraggableColumnDirective } from '../../dragdrop/draggable-column.directive'; import { DragHintService } from '../../dragdrop/drag-hint.service'; import { DropCueService } from '../../dragdrop/drop-cue.service'; import { ColumnReorderService } from '../../dragdrop/column-reorder.service'; import { position, isTargetBefore, offset } from '../../dragdrop/common'; import { SortService } from '../../common/sort.service'; import { hasItems } from '../../column-menu/utils'; import { closestInScope, isFocusable } from '../common/dom-queries'; import { SelectionService } from '../../selection/selection.service'; import { ColumnsContainer } from '../../columns/columns-container'; import { FilterRowComponent } from '../../filtering/filter-row.component'; import { ColumnHandleDirective } from '../../column-resizing/column-handle.directive'; import { FocusableDirective } from '../../navigation/focusable.directive'; import { ColumnMenuComponent } from '../../column-menu/column-menu.component'; import { FilterMenuComponent } from '../../filtering/menu/filter-menu.component'; import { LogicalCellDirective } from '../../navigation/logical-cell.directive'; import { LogicalRowDirective } from '../../navigation/logical-row.directive'; import { CheckBoxComponent } from '@progress/kendo-angular-inputs'; import { TreeListSelectAllCheckboxDirective } from './select-all-checkbox.directive'; import { ColumnInfoService } from '../../common/column-info.service'; import { ContextService } from '../../common/provider.service'; import { NavigationService } from '../../navigation/navigation.service'; import { IdService } from '../../common/id.service'; import { ColumnReorderEvent } from '../../dragdrop/column-reorder-event'; import * as i0 from "@angular/core"; import * as i1 from "../../common/single-popup.service"; import * as i2 from "../../dragdrop/drag-hint.service"; import * as i3 from "../../dragdrop/drop-cue.service"; import * as i4 from "../../dragdrop/column-reorder.service"; import * as i5 from "../../common/id.service"; import * as i6 from "../../common/sort.service"; import * as i7 from "../../selection/selection.service"; import * as i8 from "@progress/kendo-angular-l10n"; import * as i9 from "../../common/column-info.service"; import * as i10 from "../../common/provider.service"; import * as i11 from "../../navigation/navigation.service"; const mergeObjects = (...args) => Object.assign.apply(null, [{}].concat(args)); const directions = initialDirection => initialDirection === "asc" ? ["asc", "desc"] : ["desc", "asc"]; /** * @hidden */ const isRootLevel = ({ parent }) => !isTruthy(parent); const ofColumnType = ({ draggable }) => ['column', 'columnGroup'] .indexOf(draggable.context.type) >= 0; const notSameElement = ({ draggable, target }) => draggable.element.nativeElement !== target.element.nativeElement; const inSameParent = (x, y) => x.parent === y.parent || (isInSpanColumn(y) && inSameParent(x, y.parent)); const sameParent = ({ draggable, target }) => inSameParent(draggable.context.column, target.context.column); const lastNonLocked = ({ draggable }) => !isTruthy(draggable.context.column.locked) && isRootLevel(draggable.context.column) && draggable.context.lastColumn; const notInSpanColumn = ({ draggable }) => !isInSpanColumn(draggable.context.column); const reorderable = ({ draggable }) => draggable.context.column.reorderable; const lockable = ({ draggable, target }) => draggable.context.column.lockable !== false || draggable.context.column.isLocked === target.context.column.isLocked; const rules = and(ofColumnType, reorderable, notInSpanColumn, notSameElement, sameParent, not(lastNonLocked), lockable); const modifierKeys = ['alt', 'ctrl', 'shift', 'meta']; /** * @hidden */ export class HeaderComponent { popupService; hint; cue; reorderService; idService; sortService; selectionService; localization; cd; columnInfoService; contextService; navigationService; /** * @hidden */ totalColumnLevels; columns = []; scrollable; filterable; sort = new Array(); filter; sortable = false; lockedColumnsCount = 0; resizable = false; reorderable = false; columnMenu = false; columnMenuTemplate; totalColumnsCount = 0; totalColumns; tabIndex; get isNavigable() { return this.navigationService.enabled; } sortedFields = {}; get headerClass() { return !this.scrollable; } hostClass = true; get sortableLabel() { return this.localization.get('sortable'); } get columnMenuSettings() { return this.columnMenu; } dropTargets = new QueryList(); filterMenus; columnMenus; // Number of unlocked columns in the next table, if any get unlockedColumnsCount() { return this.totalColumnsCount - this.lockedColumnsCount - this.columns.length; } sortAscSmallIcon = sortAscSmallIcon; sortDescSmallIcon = sortDescSmallIcon; subscription = new Subscription(); targetSubscription; stopSorting = false; _leafColumns; constructor(popupService, hint, cue, reorderService, idService, sortService, selectionService, localization, cd, columnInfoService, contextService, navigationService) { this.popupService = popupService; this.hint = hint; this.cue = cue; this.reorderService = reorderService; this.idService = idService; this.sortService = sortService; this.selectionService = selectionService; this.localization = localization; this.cd = cd; this.columnInfoService = columnInfoService; this.contextService = contextService; this.navigationService = navigationService; } ngAfterViewInit() { this.subscription.add(observe(this.dropTargets) .subscribe(this.attachTargets.bind(this))); } ngDoCheck() { this._leafColumns = columnsToRender(this.columns || []).filter(x => !isColumnGroupComponent(x)); } ngOnChanges(changes) { const sortChange = changes.sort; if (sortChange && !sortChange.isFirstChange()) { sortChange.currentValue.forEach(change => { this.sortedFields[change.field] = true; }); } } ngOnInit() { this.subscription.add(this.localization.changes .subscribe(() => this.cd.markForCheck())); } ngOnDestroy() { if (this.targetSubscription) { this.targetSubscription.unsubscribe(); } if (this.popupService) { this.popupService.destroy(); } this.subscription.unsubscribe(); } getColumnComponent(column) { return column; } onSortClick(column, event, link) { if (this.stopSorting) { this.stopSorting = false; return; } const target = event.target; if (column.headerTemplateRef && target !== link) { const hasFocusableParent = Boolean(closestInScope(target, isFocusable, link)); if (hasFocusableParent) { // Do not sort when clicking focusable template elements. return; } } const modifier = this.matchModifier(event); const toggledColumn = this.toggleSort(column, modifier); this.sortColumn(toggledColumn); } selectAllCheckboxId() { return this.idService.selectAllCheckboxId(); } get selectAllCheckboxLabel() { return this.contextService.localization.get('selectAllRowsCheckboxLabel'); } sortColumn(descriptor) { this.sortService.sort(descriptor); } /** * * Determines whether the modifier key (if any) passed * with a click/keyboard event matches the user-defined multiSortKey. */ matchModifier(event) { const { multiSortKey } = normalize(this.sortable); if (multiSortKey === 'none') { return modifierKeys.every(key => !event[`${key}Key`]); } return multiSortKey === 'ctrl' ? event.ctrlKey || event.metaKey : event[`${multiSortKey}Key`]; } onHeaderKeydown(column, args) { if (args.keyCode === Keys.ArrowDown && args.altKey && this.showFilterMenu) { args.preventDefault(); args.stopImmediatePropagation(); const filterMenu = this.filterMenus.find(fm => fm.column === column); filterMenu.toggle(filterMenu.anchor.nativeElement, filterMenu.template); return; } if (args.keyCode === Keys.ArrowDown && args.altKey && this.showColumnMenu(column)) { args.preventDefault(); args.stopImmediatePropagation(); const columnMenu = this.columnMenus.find(cm => cm.column === column); columnMenu.toggle(null, columnMenu.anchor.nativeElement, columnMenu.template); return; } const isCtrlOrMeta = args.ctrlKey || args.metaKey; const isLeftOrRightArrow = args.keyCode === Keys.ArrowLeft || args.keyCode === Keys.ArrowRight; const isReorderingKeyShortcut = isLeftOrRightArrow && isCtrlOrMeta; if (isReorderingKeyShortcut && this.isReorderable(column)) { args.preventDefault(); const columnsCount = this.columnInfoService.leafNamedColumns.length; const reorderDirection = args.keyCode === Keys.ArrowLeft ? -1 : 1; const rtlMultiplier = this.contextService.localization.rtl ? -1 : 1; const reorderDirectionOffset = reorderDirection * rtlMultiplier; const newIndex = column.leafIndex + reorderDirectionOffset; const normalizedNewIndex = Math.min(Math.max(0, newIndex), columnsCount - 1); const treelistInstance = this.contextService.treelist; treelistInstance.reorderColumn(column, normalizedNewIndex, { before: reorderDirectionOffset < 0 }); treelistInstance.columnReorder.emit(new ColumnReorderEvent({ column, newIndex: normalizedNewIndex, oldIndex: column.leafIndex })); return; } if (!this.sortable || args.defaultPrevented || column.sortable === false) { return; } if (args.keyCode === Keys.Enter && isPresent(column.field)) { const modifier = this.matchModifier(args); this.sortService.sort(this.toggleSort(column, modifier)); } } showSortNumbering(column) { const { showIndexes } = normalize(this.sortable); return showIndexes && this.sort && this.sort.filter(({ dir }) => isPresent(dir)).length > 1 && this.sortOrder(column.field) > 0; } sortOrder(field) { return this.sort .filter(({ dir }) => isPresent(dir)) .findIndex(x => x.field === field) + 1; } sortState(column) { if (!this.isSortable(column)) { return; } const state = this.sortDescriptor(column.field); if (state.dir === 'asc') { return 'ascending'; } if (state.dir === 'desc') { return 'descending'; } } /** * * @param column * @param modifier - Indicates whether the client-defined `multiSortKey` modifier is met. Defaults to `true`. * @returns - SortDescriptor[] */ toggleSort(column, modifier = true) { const { allowUnsort, mode, initialDirection } = normalize(this.sortable, column.sortable); const descriptor = this.toggleDirection(column.field, allowUnsort, initialDirection); if (mode === 'single' || !modifier) { return [descriptor]; } return [...this.sort.filter(desc => desc.field !== column.field), descriptor]; } isFirstOnRow(column, index) { const isTailing = (c) => c && (this.columnsForLevel(c.level).indexOf(c) > 0 || isTailing(c.parent)); return index === 0 && isTailing(column.parent); } logicalColumnIndex(column) { const index = column.leafIndex; if (isPresent(index)) { return index; } return -1; } get showFilterMenu() { return !this.columnMenu && hasFilterMenu(this.filterable); } get showFilterRow() { return hasFilterRow(this.filterable); } showColumnMenu(column) { return this.columnMenu && !isCheckboxColumn(column) && column.columnMenu && (this.columnMenuTemplate || column.columnMenuTemplates.length || hasItems(this.columnMenu, column)); } isFilterable(column) { return !isNullOrEmptyString(column.field) && column.filterable === true; } canDrop(draggable, target) { return this.reorderable && rules({ draggable, target }); } isSortable(column) { return !isNullOrEmptyString(column.field) && isTruthy(this.sortable) && isTruthy(column.sortable); } trackByIndex(index, _item) { return index; } shouldActivate(column) { const canReorder = this.isReorderable(column); if (!canReorder && !isColumnComponent(column)) { return false; } return canReorder; } isInteractive(column, prop) { return !isNullOrEmptyString(column.field) && isTruthy(this[prop]) && isTruthy(column[prop]); } isCheckboxColumn(column) { return isCheckboxColumn(column) && !column.templateRef; } isReorderable(column) { return this.reorderable && column.reorderable; } toggleDirection(field, allowUnsort, initialDirection) { const descriptor = this.sortDescriptor(field); const [first, second] = directions(initialDirection); let dir = first; if (descriptor.dir === first) { dir = second; } else if (descriptor.dir === second && allowUnsort) { dir = undefined; } return { dir, field }; } columnsForLevel(level) { const columns = this.columns ? this.columns.filter(column => column.level === level) : []; return sortColumns(columnsToRender(columns)); } isColumnGroupComponent(column) { return isColumnGroupComponent(column); } get columnLevels() { return new Array((this.totalColumnLevels || 0) + 1); } renderSelectAll(column) { return column.isCheckboxColumn && column.showSelectAll && !column.headerTemplateRef && this.selectionService.enableMultiple; } selectAllChange(state) { this.selectionService.toggleAll(state); } sortDescriptor(field) { return this.sort.find(item => item.field === field) || { field }; } get leafColumns() { return this._leafColumns; } messageFor(token) { return this.localization.get(token); } attachTargets() { if (this.targetSubscription) { this.targetSubscription.unsubscribe(); } this.targetSubscription = new Subscription(); const enterStream = merge(...this.dropTargets.map(target => target.enter)); const leaveStream = merge(...this.dropTargets.map(target => target.leave)); const dropStream = merge(...this.dropTargets.map(target => target.drop)); this.targetSubscription.add(enterStream.pipe(tap(({ target, draggable }) => { const targetLocked = isTruthy(target.context.column.isLocked); const draggableLocked = isTruthy(draggable.context.column.isLocked); if (this.lockedColumnsCount > 0 || targetLocked || draggableLocked) { this.hint.toggleLock(targetLocked); } }), filter(({ draggable, target }) => this.canDrop(draggable, target)), switchMap(this.trackMove.bind(this, leaveStream, dropStream)), map((e) => mergeObjects(e, { before: this.calculateBefore(e), changeContainer: e.changeContainer })), map(this.normalizeTarget.bind(this)), tap(this.enter.bind(this)), switchMap((args) => dropStream.pipe(map(() => args), takeUntil(leaveStream.pipe(tap(this.leave.bind(this))))))) .subscribe(this.drop.bind(this))); } normalizeTarget(e) { let target = e.target; const parent = target.context.column.parent; if (parent && parent.isSpanColumn) { const arr = this.dropTargets.toArray(); const firstSpan = arr.find(t => t.context.column.parent === parent); const index = arr.indexOf(firstSpan); const adjust = e.before ? 0 : parent.childColumns.length - 1; target = arr[index + adjust]; } return mergeObjects(e, { target }); } trackMove(leaveStream, dropStream, e) { const column = e.target.context.column; const levelColumns = this.columnsForLevel(column.level); const index = levelColumns.indexOf(column); const isFirst = (column.locked ? index === levelColumns.length - 1 : index === 0); const changed = e.draggable.context.column.isLocked !== column.isLocked; if (changed && isFirst) { return e.draggable.drag .pipe(takeUntil(leaveStream), takeUntil(dropStream), map(({ mouseEvent }) => mergeObjects({ changeContainer: true }, e, { mouseEvent }))); } return of(mergeObjects({ changeContainer: changed }, e)); } calculateBefore({ draggable, target, mouseEvent, changeContainer = false }) { const targetElement = target.element.nativeElement; let before = false; if (changeContainer) { const { left } = offset(targetElement); const halfWidth = targetElement.offsetWidth / 2; const middle = left + halfWidth; before = middle > mouseEvent.pageX; if (this.localization.rtl) { before = !before; } } else { before = isTargetBefore(draggable.element.nativeElement, targetElement); } return before; } enter({ target, before }) { this.hint.enable(); if (this.localization.rtl) { before = !before; } this.cue.position(position(target.element.nativeElement, before)); } leave() { this.hint.disable(); this.cue.hide(); } drop({ draggable, target, before, changeContainer }) { this.reorderService.reorder({ before, changeContainer, source: draggable.context.column, target: target.context.column }); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HeaderComponent, deps: [{ token: i1.SinglePopupService }, { token: i2.DragHintService }, { token: i3.DropCueService }, { token: i4.ColumnReorderService }, { token: i5.IdService }, { token: i6.SortService }, { token: i7.SelectionService }, { token: i8.LocalizationService }, { token: i0.ChangeDetectorRef }, { token: i9.ColumnInfoService }, { token: i10.ContextService }, { token: i11.NavigationService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: HeaderComponent, isStandalone: true, selector: "[kendoTreeListHeader]", inputs: { totalColumnLevels: "totalColumnLevels", columns: "columns", scrollable: "scrollable", filterable: "filterable", sort: "sort", filter: "filter", sortable: "sortable", lockedColumnsCount: "lockedColumnsCount", resizable: "resizable", reorderable: "reorderable", columnMenu: "columnMenu", columnMenuTemplate: "columnMenuTemplate", totalColumnsCount: "totalColumnsCount", totalColumns: "totalColumns", tabIndex: "tabIndex" }, host: { properties: { "class.k-grid-header": "this.headerClass", "class.k-table-thead": "this.hostClass" } }, viewQueries: [{ propertyName: "dropTargets", predicate: DropTargetDirective, descendants: true }, { propertyName: "filterMenus", predicate: FilterMenuComponent, descendants: true }, { propertyName: "columnMenus", predicate: ColumnMenuComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: ` <tr *ngFor="let i of columnLevels; let levelIndex = index" role="row" kendoTreeListLogicalRow [logicalRowIndex]="levelIndex" [logicalSlaveRow]="lockedColumnsCount > 0" [logicalCellsCount]="columns.length" [totalColumns]="totalColumns" [logicalSlaveCellsCount]="unlockedColumnsCount"> <ng-template ngFor let-column="$implicit" [ngForOf]="columnsForLevel(levelIndex)" [ngForTrackBy]="trackByIndex" let-columnIndex="index" let-last="last"> <th *ngIf="!isColumnGroupComponent(column)" kendoTreeListLogicalCell [logicalRowIndex]="levelIndex" [logicalColIndex]="logicalColumnIndex(column)" [headerLabelText]="column.title || getColumnComponent(column).field" [colSpan]="column.colspan" [rowSpan]="column.rowspan(totalColumnLevels)" role="columnheader" aria-selected="false" [attr.aria-sort]="sortState(getColumnComponent(column))" [class.k-sorted]="sortState(getColumnComponent(column))" (keydown)="onHeaderKeydown(getColumnComponent(column), $event)" kendoDropTarget kendoDraggable kendoDraggableColumn [enableDrag]="shouldActivate(column)" [context]="{ field: getColumnComponent(column).field, type: 'column', column: column, hint: column.title || getColumnComponent(column).field, lastColumn: last && columnIndex === 0 }" class="k-header k-table-th" [class.k-filterable]="(showFilterMenu && isFilterable(getColumnComponent(column))) || showColumnMenu(column)" [class.k-first]="isFirstOnRow(getColumnComponent(column), columnIndex)" [ngClass]="column.headerClass" [ngStyle]="column.headerStyle" [attr.rowspan]="column.rowspan(totalColumnLevels)" [attr.colspan]="column.colspan" [attr.aria-haspopup]="isNavigable && (showFilterMenu || showColumnMenu(column)) ? 'dialog' : undefined" [attr.aria-expanded]="isNavigable && (showFilterMenu || showColumnMenu(column)) ? false : undefined" [attr.aria-keyshortcuts]="isNavigable && (showFilterMenu || showColumnMenu(column)) ? 'Alt + ArrowDown' : undefined"> <ng-container *ngIf="!isInteractive(getColumnComponent(column), 'sortable')"> <span class="k-cell-inner"> <span class="k-link" [class.!k-cursor-default]="!isInteractive(getColumnComponent(column), 'reorderable')"> <ng-template [templateContext]="{ templateRef: column.headerTemplateRef, columnIndex: column.leafIndex, column: column, $implicit: column }"> </ng-template> <ng-container *ngIf="!column.headerTemplateRef"> <span class="k-column-title">{{column.displayTitle}}</span> </ng-container> </span> <kendo-treelist-filter-menu *ngIf="showFilterMenu && isFilterable(getColumnComponent(column))" [column]="getColumnComponent(column)" [filter]="filter" [tabIndex]="tabIndex"> </kendo-treelist-filter-menu> <kendo-treelist-column-menu *ngIf="showColumnMenu(column)" [standalone]="false" [settings]="columnMenuSettings" [column]="column" [columnMenuTemplate]="columnMenuTemplate" [sort]="sort" [filter]="filter" [sortable]="sortable" [tabIndex]="tabIndex"> </kendo-treelist-column-menu> </span> </ng-container> <ng-container *ngIf="isInteractive(getColumnComponent(column), 'sortable')"> <span class="k-cell-inner"> <span #link class="k-link" (click)="onSortClick(getColumnComponent(column), $event, link)"> <ng-template [templateContext]="{ templateRef: column.headerTemplateRef, columnIndex: column.leafIndex, column: column, $implicit: column }"> </ng-template> <ng-container *ngIf="!column.headerTemplateRef"> <span class="k-column-title">{{column.displayTitle}}</span> </ng-container> <span [class.k-sort-icon]="sortDescriptor(getColumnComponent(column).field).dir"> <kendo-icon-wrapper *ngIf="sortDescriptor(getColumnComponent(column).field).dir" role="note" [attr.aria-label]="sortableLabel" name="sort-{{sortDescriptor(getColumnComponent(column).field).dir}}-small" [svgIcon]="sortDescriptor(getColumnComponent(column).field).dir === 'asc' ? sortAscSmallIcon : sortDescSmallIcon" ></kendo-icon-wrapper> </span> <span *ngIf="showSortNumbering(getColumnComponent(column))" class="k-sort-order">{{sortOrder(getColumnComponent(column).field)}}</span> </span> <kendo-treelist-filter-menu *ngIf="showFilterMenu && isFilterable(getColumnComponent(column))" [column]="getColumnComponent(column)" [filter]="filter" [tabIndex]="tabIndex"> </kendo-treelist-filter-menu> <kendo-treelist-column-menu *ngIf="showColumnMenu(column)" [standalone]="false" [settings]="columnMenuSettings" [column]="column" [columnMenuTemplate]="columnMenuTemplate" [sort]="sort" [filter]="filter" [sortable]="sortable" [tabIndex]="tabIndex"> </kendo-treelist-column-menu> </span> </ng-container> <ng-container *ngIf="isCheckboxColumn(column) && !column.headerTemplateRef && $any(column).showSelectAll"> <kendo-checkbox [attr.id]="selectAllCheckboxId()" [inputAttributes]="{'aria-label': selectAllCheckboxLabel}" kendoTreeListSelectAllCheckbox kendoTreeListFocusable (checkedStateChange)="selectAllChange($event)" ></kendo-checkbox> </ng-container> <span kendoTreeListColumnHandle kendoDraggable class="k-column-resizer" *ngIf="resizable" [column]="column" [columns]="columns"> </span> </th> <th *ngIf="isColumnGroupComponent(column)" kendoTreeListLogicalCell [logicalRowIndex]="levelIndex" [logicalColIndex]="logicalColumnIndex(column)" [rowSpan]="column.rowspan(totalColumnLevels)" [colSpan]="column.colspan" [headerLabelText]="column.title || getColumnComponent(column).field" kendoDropTarget kendoDraggable kendoDraggableColumn [enableDrag]="shouldActivate(column)" [context]="{ type: 'columnGroup', column: column, hint: column.title, lastColumn: last && columnIndex === 0 }" class="k-header k-table-th" [class.k-first]="isFirstOnRow(getColumnComponent(column), columnIndex)" [attr.aria-haspopup]="(isNavigable && showColumnMenu(column)) ? 'dialog' : undefined" [attr.aria-expanded]="(isNavigable && showColumnMenu(column)) ? false : undefined" [attr.aria-keyshortcuts]="isNavigable && showColumnMenu(column) ? 'Alt + ArrowDown' : undefined" [ngClass]="column.headerClass" [ngStyle]="column.headerStyle" [attr.rowspan]="column.rowspan(totalColumnLevels)" [attr.colspan]="column.colspan"> <span class="k-cell-inner"> <span class="k-link" [class.!k-cursor-default]="!isInteractive(getColumnComponent(column), 'reorderable')"> <ng-template [templateContext]="{ templateRef: column.headerTemplateRef, columnIndex: lockedColumnsCount + columnIndex, column: column, $implicit: column }"> </ng-template> <ng-container *ngIf="!column.headerTemplateRef"> <span class="k-column-title">{{column.displayTitle}}</span> </ng-container> </span> <kendo-treelist-column-menu *ngIf="showColumnMenu(column)" [standalone]="false" [settings]="columnMenuSettings" [column]="column" [columnMenuTemplate]="columnMenuTemplate"> </kendo-treelist-column-menu> </span> <span kendoTreeListColumnHandle kendoDraggable class="k-column-resizer" *ngIf="resizable" [column]="column" [columns]="columns"> </span> </th> </ng-template> </tr> <tr *ngIf="showFilterRow" kendoTreeListFilterRow [columns]="leafColumns" [filter]="filter" [lockedColumnsCount]="lockedColumnsCount" kendoTreeListLogicalRow [totalColumns]="totalColumns" [logicalRowIndex]="totalColumnLevels + 1" [logicalSlaveRow]="lockedColumnsCount > 0" [logicalCellsCount]="columns.length" [logicalSlaveCellsCount]="unlockedColumnsCount"></tr> `, isInline: true, dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: LogicalRowDirective, selector: "[kendoTreeListLogicalRow]", inputs: ["logicalRowIndex", "logicalSlaveRow", "logicalCellsCount", "logicalSlaveCellsCount", "dataRowIndex", "dataItem", "isNew", "totalColumns"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: LogicalCellDirective, selector: "[kendoTreeListLogicalCell]", inputs: ["logicalColIndex", "logicalRowIndex", "logicalSlaveCell", "column", "colIndex", "colSpan", "rowSpan", "dataRowIndex", "dataItem", "expandable", "headerLabelText"] }, { kind: "directive", type: DropTargetDirective, selector: "[kendoDropTarget]", inputs: ["context"], outputs: ["enter", "leave", "drop"] }, { kind: "directive", type: DraggableDirective, selector: "[kendoDraggable]", inputs: ["enableDrag"], outputs: ["kendoPress", "kendoDrag", "kendoRelease"] }, { kind: "directive", type: DraggableColumnDirective, selector: "[kendoDraggableColumn]", inputs: ["context", "enableDrag"], outputs: ["drag"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: FilterMenuComponent, selector: "kendo-treelist-filter-menu", inputs: ["column", "filter", "tabIndex"] }, { kind: "component", type: ColumnMenuComponent, selector: "kendo-treelist-column-menu", inputs: ["standalone", "column", "settings", "sort", "filter", "sortable", "columnMenuTemplate", "tabIndex"] }, { kind: "directive", type: TemplateContextDirective, selector: "[templateContext]", inputs: ["templateContext"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }, { kind: "directive", type: FocusableDirective, selector: "[kendoTreeListFocusable],\n [kendoTreeListAddCommand],\n [kendoTreeListEditCommand],\n [kendoTreeListRemoveCommand],\n [kendoTreeListSaveCommand],\n [kendoTreeListCancelCommand]\n ", inputs: ["kendoTreeListFocusable", "enabled", "kendoTreeListAddCommand", "kendoTreeListEditCommand", "kendoTreeListRemoveCommand", "kendoTreeListSaveCommand", "kendoTreeListCancelCommand"] }, { kind: "directive", type: ColumnHandleDirective, selector: "[kendoTreeListColumnHandle]", inputs: ["columns", "column"] }, { kind: "component", type: FilterRowComponent, selector: "[kendoTreeListFilterRow]", inputs: ["columns", "filter", "logicalRowIndex", "lockedColumnsCount"] }, { kind: "component", type: CheckBoxComponent, selector: "kendo-checkbox", inputs: ["checkedState", "rounded"], outputs: ["checkedStateChange"], exportAs: ["kendoCheckBox"] }, { kind: "directive", type: TreeListSelectAllCheckboxDirective, selector: "[kendoTreeListSelectAllCheckbox]" }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HeaderComponent, decorators: [{ type: Component, args: [{ selector: '[kendoTreeListHeader]', template: ` <tr *ngFor="let i of columnLevels; let levelIndex = index" role="row" kendoTreeListLogicalRow [logicalRowIndex]="levelIndex" [logicalSlaveRow]="lockedColumnsCount > 0" [logicalCellsCount]="columns.length" [totalColumns]="totalColumns" [logicalSlaveCellsCount]="unlockedColumnsCount"> <ng-template ngFor let-column="$implicit" [ngForOf]="columnsForLevel(levelIndex)" [ngForTrackBy]="trackByIndex" let-columnIndex="index" let-last="last"> <th *ngIf="!isColumnGroupComponent(column)" kendoTreeListLogicalCell [logicalRowIndex]="levelIndex" [logicalColIndex]="logicalColumnIndex(column)" [headerLabelText]="column.title || getColumnComponent(column).field" [colSpan]="column.colspan" [rowSpan]="column.rowspan(totalColumnLevels)" role="columnheader" aria-selected="false" [attr.aria-sort]="sortState(getColumnComponent(column))" [class.k-sorted]="sortState(getColumnComponent(column))" (keydown)="onHeaderKeydown(getColumnComponent(column), $event)" kendoDropTarget kendoDraggable kendoDraggableColumn [enableDrag]="shouldActivate(column)" [context]="{ field: getColumnComponent(column).field, type: 'column', column: column, hint: column.title || getColumnComponent(column).field, lastColumn: last && columnIndex === 0 }" class="k-header k-table-th" [class.k-filterable]="(showFilterMenu && isFilterable(getColumnComponent(column))) || showColumnMenu(column)" [class.k-first]="isFirstOnRow(getColumnComponent(column), columnIndex)" [ngClass]="column.headerClass" [ngStyle]="column.headerStyle" [attr.rowspan]="column.rowspan(totalColumnLevels)" [attr.colspan]="column.colspan" [attr.aria-haspopup]="isNavigable && (showFilterMenu || showColumnMenu(column)) ? 'dialog' : undefined" [attr.aria-expanded]="isNavigable && (showFilterMenu || showColumnMenu(column)) ? false : undefined" [attr.aria-keyshortcuts]="isNavigable && (showFilterMenu || showColumnMenu(column)) ? 'Alt + ArrowDown' : undefined"> <ng-container *ngIf="!isInteractive(getColumnComponent(column), 'sortable')"> <span class="k-cell-inner"> <span class="k-link" [class.!k-cursor-default]="!isInteractive(getColumnComponent(column), 'reorderable')"> <ng-template [templateContext]="{ templateRef: column.headerTemplateRef, columnIndex: column.leafIndex, column: column, $implicit: column }"> </ng-template> <ng-container *ngIf="!column.headerTemplateRef"> <span class="k-column-title">{{column.displayTitle}}</span> </ng-container> </span> <kendo-treelist-filter-menu *ngIf="showFilterMenu && isFilterable(getColumnComponent(column))" [column]="getColumnComponent(column)" [filter]="filter" [tabIndex]="tabIndex"> </kendo-treelist-filter-menu> <kendo-treelist-column-menu *ngIf="showColumnMenu(column)" [standalone]="false" [settings]="columnMenuSettings" [column]="column" [columnMenuTemplate]="columnMenuTemplate" [sort]="sort" [filter]="filter" [sortable]="sortable" [tabIndex]="tabIndex"> </kendo-treelist-column-menu> </span> </ng-container> <ng-container *ngIf="isInteractive(getColumnComponent(column), 'sortable')"> <span class="k-cell-inner"> <span #link class="k-link" (click)="onSortClick(getColumnComponent(column), $event, link)"> <ng-template [templateContext]="{ templateRef: column.headerTemplateRef, columnIndex: column.leafIndex, column: column, $implicit: column }"> </ng-template> <ng-container *ngIf="!column.headerTemplateRef"> <span class="k-column-title">{{column.displayTitle}}</span> </ng-container> <span [class.k-sort-icon]="sortDescriptor(getColumnComponent(column).field).dir"> <kendo-icon-wrapper *ngIf="sortDescriptor(getColumnComponent(column).field).dir" role="note" [attr.aria-label]="sortableLabel" name="sort-{{sortDescriptor(getColumnComponent(column).field).dir}}-small" [svgIcon]="sortDescriptor(getColumnComponent(column).field).dir === 'asc' ? sortAscSmallIcon : sortDescSmallIcon" ></kendo-icon-wrapper> </span> <span *ngIf="showSortNumbering(getColumnComponent(column))" class="k-sort-order">{{sortOrder(getColumnComponent(column).field)}}</span> </span> <kendo-treelist-filter-menu *ngIf="showFilterMenu && isFilterable(getColumnComponent(column))" [column]="getColumnComponent(column)" [filter]="filter" [tabIndex]="tabIndex"> </kendo-treelist-filter-menu> <kendo-treelist-column-menu *ngIf="showColumnMenu(column)" [standalone]="false" [settings]="columnMenuSettings" [column]="column" [columnMenuTemplate]="columnMenuTemplate" [sort]="sort" [filter]="filter" [sortable]="sortable" [tabIndex]="tabIndex"> </kendo-treelist-column-menu> </span> </ng-container> <ng-container *ngIf="isCheckboxColumn(column) && !column.headerTemplateRef && $any(column).showSelectAll"> <kendo-checkbox [attr.id]="selectAllCheckboxId()" [inputAttributes]="{'aria-label': selectAllCheckboxLabel}" kendoTreeListSelectAllCheckbox kendoTreeListFocusable (checkedStateChange)="selectAllChange($event)" ></kendo-checkbox> </ng-container> <span kendoTreeListColumnHandle kendoDraggable class="k-column-resizer" *ngIf="resizable" [column]="column" [columns]="columns"> </span> </th> <th *ngIf="isColumnGroupComponent(column)" kendoTreeListLogicalCell [logicalRowIndex]="levelIndex" [logicalColIndex]="logicalColumnIndex(column)" [rowSpan]="column.rowspan(totalColumnLevels)" [colSpan]="column.colspan" [headerLabelText]="column.title || getColumnComponent(column).field" kendoDropTarget kendoDraggable kendoDraggableColumn [enableDrag]="shouldActivate(column)" [context]="{ type: 'columnGroup', column: column, hint: column.title, lastColumn: last && columnIndex === 0 }" class="k-header k-table-th" [class.k-first]="isFirstOnRow(getColumnComponent(column), columnIndex)" [attr.aria-haspopup]="(isNavigable && showColumnMenu(column)) ? 'dialog' : undefined" [attr.aria-expanded]="(isNavigable && showColumnMenu(column)) ? false : undefined" [attr.aria-keyshortcuts]="isNavigable && showColumnMenu(column) ? 'Alt + ArrowDown' : undefined" [ngClass]="column.headerClass" [ngStyle]="column.headerStyle" [attr.rowspan]="column.rowspan(totalColumnLevels)" [attr.colspan]="column.colspan"> <span class="k-cell-inner"> <span class="k-link" [class.!k-cursor-default]="!isInteractive(getColumnComponent(column), 'reorderable')"> <ng-template [templateContext]="{ templateRef: column.headerTemplateRef, columnIndex: lockedColumnsCount + columnIndex, column: column, $implicit: column }"> </ng-template> <ng-container *ngIf="!column.headerTemplateRef"> <span class="k-column-title">{{column.displayTitle}}</span> </ng-container> </span> <kendo-treelist-column-menu *ngIf="showColumnMenu(column)" [standalone]="false" [settings]="columnMenuSettings" [column]="column" [columnMenuTemplate]="columnMenuTemplate"> </kendo-treelist-column-menu> </span> <span kendoTreeListColumnHandle kendoDraggable class="k-column-resizer" *ngIf="resizable" [column]="column" [columns]="columns"> </span> </th> </ng-template> </tr> <tr *ngIf="showFilterRow" kendoTreeListFilterRow [columns]="leafColumns" [filter]="filter" [lockedColumnsCount]="lockedColumnsCount" kendoTreeListLogicalRow [totalColumns]="totalColumns" [logicalRowIndex]="totalColumnLevels + 1" [logicalSlaveRow]="lockedColumnsCount > 0" [logicalCellsCount]="columns.length" [logicalSlaveCellsCount]="unlockedColumnsCount"></tr> `, standalone: true, imports: [NgFor, LogicalRowDire