igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
678 lines (675 loc) • 353 kB
JavaScript
import { __decorate } from 'tslib';
import * as i0 from '@angular/core';
import { inject, ElementRef, HostListener, ChangeDetectionStrategy, Component, HostBinding, ViewChild, Input, Renderer2, ViewChildren, Injectable, NgZone, Injector, EnvironmentInjector, ViewContainerRef, createComponent, TemplateRef, Directive, Pipe, forwardRef, EventEmitter, booleanAttribute, Output, ContentChild, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectorRef, NgModule } from '@angular/core';
import { NgTemplateOutlet, NgClass, NgStyle } from '@angular/common';
import { takeUntil, take, timeout, first } from 'rxjs/operators';
import { IgxGridHeaderComponent, IgxPivotColumnResizingService, PivotRowLayoutType, PivotUtil, SortingIndexPipe, IgxGridHeaderGroupComponent, IGX_GRID_BASE, IgxColumnMovingDragDirective, IgxColumnMovingDropDirective, IgxPivotResizeHandleDirective, IgxHeaderGroupStylePipe, IgxGridHeaderRowComponent, DropPosition, IgxGridExcelStyleFilteringComponent, IgxExcelStyleColumnOperationsTemplateDirective, IgxExcelStyleFilterOperationsTemplateDirective, IgxExcelStyleSearchComponent, IgxGridTopLevelColumns, IgxGridNavigationService, PivotSummaryPosition, IgxFilteringService, DimensionValuesFilteringStrategy, IgxColumnComponent, DEFAULT_PIVOT_KEYS, PivotRowDimensionsStrategy, PivotColumnDimensionsStrategy, GridBaseAPIService, IgxRowDirective, IgxGridCellComponent, IgxGridNotGroupedPipe, IgxGridCellStylesPipe, IgxGridTransactionStatePipe, FilterMode, PivotDimensionType, NoopPivotDimensionsStrategy, IgxPivotDateDimension, IgxColumnGroupComponent, IgxGridBodyDirective, IgxGridDragSelectDirective, IgxPivotGridColumnResizerComponent, IgxGridRowClassesPipe, IgxGridRowStylesPipe, IgxGridCRUDService, IgxGridValidationService, IgxGridSummaryService, IgxGridSelectionService, IgxColumnResizingService, IGX_GRID_SERVICE_BASE, WatchChanges, IgxGridFooterComponent, IgxAdvancedFilteringDialogComponent, IgxRowExpandedIndicatorDirective, IgxRowCollapsedIndicatorDirective, IgxHeaderExpandedIndicatorDirective, IgxHeaderCollapsedIndicatorDirective, IgxExcelStyleHeaderIconDirective, IgxSortAscendingHeaderIconDirective, IgxSortDescendingHeaderIconDirective, IgxSortHeaderIconDirective, IgxDragIndicatorIconDirective, IgxRowDragGhostDirective, IgxGridStateDirective, IgxGridPinningActionsComponent, IgxGridEditingActionsComponent, IgxGridActionsBaseDirective, IgxGridActionButtonComponent, IgxFilterCellTemplateDirective, IgxSummaryTemplateDirective, IgxCellTemplateDirective, IgxCellValidationErrorDirective, IgxCellHeaderTemplateDirective, IgxCellFooterTemplateDirective, IgxCellEditorTemplateDirective, IgxCollapsibleIndicatorTemplateDirective, IgxColumnLayoutComponent, IgxColumnActionsComponent, IgxColumnHidingDirective, IgxColumnPinningDirective, IgxRowSelectorDirective, IgxGroupByRowSelectorDirective, IgxHeadSelectorDirective, IgxCSVTextDirective, IgxExcelTextDirective, IgxGridToolbarActionsComponent, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarComponent, IgxGridToolbarExporterComponent, IgxGridToolbarHidingComponent, IgxGridToolbarPinningComponent, IgxGridToolbarTitleComponent, IgxGridToolbarDirective, IgxExcelStyleHeaderComponent, IgxExcelStyleSortingComponent, IgxExcelStylePinningComponent, IgxExcelStyleHidingComponent, IgxExcelStyleSelectingComponent, IgxExcelStyleClearFiltersComponent, IgxExcelStyleConditionalFilterComponent, IgxExcelStyleMovingComponent, IgxExcelStyleLoadingValuesTemplateDirective } from 'igniteui-angular/grids/core';
import { SortingDirection, VerticalAlignment, AbsoluteScrollStrategy, AutoPositionStrategy, HEADER_KEYS, ROW_EXPAND_KEYS, ROW_COLLAPSE_KEYS, FilteringExpressionsTree, FilteringLogic, DefaultSortingStrategy, GridColumnDataType, parseDate, cloneArray, FilterUtil, DataUtil, columnFieldPath, resolveNestedPath, DefaultDataCloneStrategy, ɵSize as _Size, resizeObservable, IgxOverlayOutletDirective } from 'igniteui-angular/core';
import { IgxIconComponent } from 'igniteui-angular/icon';
import { IgxDropDirective, IgxGridForOfDirective, IgxTemplateOutletDirective, IgxToggleDirective, IgxForOfSyncService, IgxForOfScrollSyncService, IgxDragDirective, IgxDragHandleDirective } from 'igniteui-angular/directives';
import { IgxChipsAreaComponent, IgxChipComponent } from 'igniteui-angular/chips';
import { IgxPrefixDirective, IgxSuffixDirective, IgxInputGroupComponent, IgxInputDirective } from 'igniteui-angular/input-group';
import { IgxBadgeComponent } from 'igniteui-angular/badge';
import { IgxDropDownItemNavigationDirective, IgxDropDownComponent, IgxDropDownItemComponent } from 'igniteui-angular/drop-down';
import { IgxCheckboxComponent } from 'igniteui-angular/checkbox';
import { IgxCircularProgressBarComponent } from 'igniteui-angular/progressbar';
import { IgxSnackbarComponent } from 'igniteui-angular/snackbar';
import { IgxGridBaseDirective } from 'igniteui-angular/grids/grid';
import { useAnimation } from '@angular/animations';
import { fadeIn, fadeOut } from 'igniteui-angular/animations';
import { IgxListComponent, IgxListItemComponent } from 'igniteui-angular/list';
import { IgxAccordionComponent } from 'igniteui-angular/accordion';
import { IgxExpansionPanelComponent, IgxExpansionPanelHeaderComponent, IgxExpansionPanelTitleDirective, IgxExpansionPanelBodyComponent } from 'igniteui-angular/expansion-panel';
/**
* @hidden
*/
class IgxPivotRowDimensionHeaderComponent extends IgxGridHeaderComponent {
constructor() {
super();
this.colResizingService = inject(IgxPivotColumnResizingService);
this.refInstance = inject((ElementRef));
this.pivotGrid = this.grid;
this.pivotGrid.dimensionsSortingExpressionsChange
.pipe(takeUntil(this._destroy$))
.subscribe((_) => this.setSortIndex());
}
ngAfterViewInit() {
this.setSortIndex();
}
onClick(event) {
event.preventDefault();
}
/**
* @hidden @internal
*/
get selectable() {
return false;
}
/**
* @hidden @internal
*/
onSortingIconClick(event) {
event.stopPropagation();
const dim = this.pivotGrid.getRowDimensionByName(this.column.field);
const startDirection = dim.sortDirection || SortingDirection.None;
const direction = startDirection + 1 > SortingDirection.Desc ?
SortingDirection.None : startDirection + 1;
this.pivotGrid.sortDimension(dim, direction);
}
getSortDirection() {
const dim = this.pivotGrid.getRowDimensionByName(this.column.field);
this.sortDirection = dim?.sortDirection || SortingDirection.None;
}
setSortIndex() {
if (this.column.sortable && this.sortIconContainer) {
const visibleRows = this.pivotGrid.pivotUI.rowLayout === PivotRowLayoutType.Vertical ?
this.pivotGrid.pivotConfiguration.rows :
PivotUtil.flatten(this.pivotGrid.pivotConfiguration.rows);
const dimIndex = visibleRows.findIndex((target) => target.memberName === this.column.field);
const dim = visibleRows[dimIndex];
let newSortIndex = -1;
if (dim.sortDirection) {
let priorSortedDims = 0;
for (let i = 0; i < dimIndex; i++) {
if (visibleRows[i].sortDirection) {
priorSortedDims++;
}
}
// Sort index starts from 1.
newSortIndex = priorSortedDims + 1;
}
this.sortIconContainer.nativeElement.setAttribute("data-sortIndex", newSortIndex >= 0 ? newSortIndex : "");
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxPivotRowDimensionHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.2", type: IgxPivotRowDimensionHeaderComponent, isStandalone: true, selector: "igx-pivot-row-dimension-header", host: { listeners: { "click": "onClick($event)" } }, usesInheritance: true, ngImport: i0, template: "<ng-template #defaultColumn>\n <span [title]=\"title\">{{ column.header || column.field }}</span>\n</ng-template>\n\n<ng-template #defaultESFHeaderIconTemplate>\n <igx-icon family=\"default\" name=\"more_vert\"></igx-icon>\n</ng-template>\n\n<ng-template #defaultSortHeaderIconTemplate>\n <igx-icon\n family=\"default\"\n [name]=\"sortDirection < 2 ? 'sort_asc' : 'sort_desc'\">\n </igx-icon>\n</ng-template>\n\n<span class=\"igx-grid-th__title\">\n <ng-container\n *ngTemplateOutlet=\"column.headerTemplate ? column.headerTemplate : defaultColumn; context: { $implicit: column, column: column}\">\n </ng-container>\n</span>\n@if (!column.columnGroup) {\n <div class=\"igx-grid-th__icons\">\n @if (column.sortable && !disabled) {\n <div #sortIconContainer class=\"sort-icon\"\n [attr.data-sortIndex]=\"(grid.sortingOptions.mode === 'single' && grid.sortingExpressions.length <=1) ? null : column.field | sortingIndex:grid.sortingExpressions\"\n (pointerdown)=\"onPointerDownIndicator($event)\" (click)=\"onSortingIconClick($event)\">\n <ng-container *ngTemplateOutlet=\"sortIconTemplate; context: { $implicit: this }\"></ng-container>\n </div>\n }\n @if (grid.allowFiltering && column.filterable && grid.filterMode === 'excelStyleFilter') {\n <div [ngClass]=\"filterIconClassName\" (pointerdown)=\"onPointerDownIndicator($event)\" (click)=\"onFilteringIconClick($event)\" >\n <ng-container *ngTemplateOutlet=\"esfIconTemplate; context: { $implicit: this }\"></ng-container>\n </div>\n }\n </div>\n}\n", dependencies: [{ kind: "component", type: IgxIconComponent, selector: "igx-icon", inputs: ["ariaHidden", "family", "name", "active"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: SortingIndexPipe, name: "sortingIndex" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxPivotRowDimensionHeaderComponent, decorators: [{
type: Component,
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'igx-pivot-row-dimension-header', imports: [IgxIconComponent, NgTemplateOutlet, NgClass, SortingIndexPipe], template: "<ng-template #defaultColumn>\n <span [title]=\"title\">{{ column.header || column.field }}</span>\n</ng-template>\n\n<ng-template #defaultESFHeaderIconTemplate>\n <igx-icon family=\"default\" name=\"more_vert\"></igx-icon>\n</ng-template>\n\n<ng-template #defaultSortHeaderIconTemplate>\n <igx-icon\n family=\"default\"\n [name]=\"sortDirection < 2 ? 'sort_asc' : 'sort_desc'\">\n </igx-icon>\n</ng-template>\n\n<span class=\"igx-grid-th__title\">\n <ng-container\n *ngTemplateOutlet=\"column.headerTemplate ? column.headerTemplate : defaultColumn; context: { $implicit: column, column: column}\">\n </ng-container>\n</span>\n@if (!column.columnGroup) {\n <div class=\"igx-grid-th__icons\">\n @if (column.sortable && !disabled) {\n <div #sortIconContainer class=\"sort-icon\"\n [attr.data-sortIndex]=\"(grid.sortingOptions.mode === 'single' && grid.sortingExpressions.length <=1) ? null : column.field | sortingIndex:grid.sortingExpressions\"\n (pointerdown)=\"onPointerDownIndicator($event)\" (click)=\"onSortingIconClick($event)\">\n <ng-container *ngTemplateOutlet=\"sortIconTemplate; context: { $implicit: this }\"></ng-container>\n </div>\n }\n @if (grid.allowFiltering && column.filterable && grid.filterMode === 'excelStyleFilter') {\n <div [ngClass]=\"filterIconClassName\" (pointerdown)=\"onPointerDownIndicator($event)\" (click)=\"onFilteringIconClick($event)\" >\n <ng-container *ngTemplateOutlet=\"esfIconTemplate; context: { $implicit: this }\"></ng-container>\n </div>\n }\n </div>\n}\n" }]
}], ctorParameters: () => [], propDecorators: { onClick: [{
type: HostListener,
args: ['click', ['$event']]
}] } });
/**
* @hidden
*/
class IgxPivotRowHeaderGroupComponent extends IgxGridHeaderGroupComponent {
constructor() {
super(...arguments);
this.grid = inject(IGX_GRID_BASE);
this.colResizingService = inject(IgxPivotColumnResizingService);
/**
* @hidden
*/
this.userSelect = 'none';
}
/**
* @hidden
*/
get role() {
return 'columnheader';
}
set dimWidth(value) {
this.column.width = value + 'px';
}
get dimWidth() {
return parseFloat(this.column.width);
}
get parent() {
return this;
}
;
get headerID() {
return `${this.grid.id}_-2_${this.rootDimension.memberName}_${this.visibleIndex}`;
}
get title() {
return this.rootDimension.displayName;
}
/**
* @hidden
* @internal
*/
get visibleIndex() {
const rows = this.grid.visibleRowDimensions;
return rows.indexOf(this.rootDimension);
}
get active() {
const nav = this.grid.navigation;
const node = nav.activeNode;
return node && !this.column.columnGroup ?
nav.isRowDimensionHeaderActive &&
node.row === this.rowIndex &&
node.column === this.visibleIndex :
false;
}
get sortAscendingStyle() {
return this.rootDimension.sortDirection === SortingDirection.Asc;
}
get sortDescendingStyle() {
return this.rootDimension.sortDirection === SortingDirection.Desc;
}
get sortableStyle() {
return true;
}
get sortedStyle() {
return this.rootDimension.sortDirection !== undefined && this.rootDimension.sortDirection !== SortingDirection.None;
}
get activeNode() {
this.grid.navigation.isRowDimensionHeaderActive = true;
this.grid.navigation.isRowHeaderActive = false;
return {
row: this.rowIndex, column: this.visibleIndex, level: null,
mchCache: {
level: 0,
visibleIndex: this.visibleIndex
},
layout: null
};
}
activate() {
this.grid.navigation.setActiveNode(this.activeNode);
}
/**
* @hidden @internal
*/
pointerdown(_event) {
this.activate();
}
/**
* @hidden @internal
*/
onMouseDown(_event) {
this.activate();
}
get selectable() {
return false;
}
getHeaderWidthFromDimension() {
return this.grid.hasHorizontalLayout && this.dimWidth === -1 ? 'fit-content' : null;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxPivotRowHeaderGroupComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.2", type: IgxPivotRowHeaderGroupComponent, isStandalone: true, selector: "igx-pivot-row-header-group", inputs: { rowIndex: "rowIndex", dimWidth: "dimWidth", rootDimension: "rootDimension" }, host: { properties: { "style.user-select": "this.userSelect", "attr.id": "this.headerID", "attr.title": "this.title", "class.igx-grid-th--active": "this.active", "class.asc": "this.sortAscendingStyle", "class.desc": "this.sortDescendingStyle", "class.igx-grid-th--sortable": "this.sortableStyle", "class.igx-grid-th--sorted": "this.sortedStyle" } }, viewQueries: [{ propertyName: "header", first: true, predicate: IgxPivotRowDimensionHeaderComponent, descendants: true }], usesInheritance: true, ngImport: i0, template: "<ng-template #defaultColumn>\n <span class=\"igx-grid-th__group-title\" [title]=\"title\">{{column.header}}</span>\n</ng-template>\n\n<ng-template #defaultCollapseIndicator>\n <igx-icon\n family=\"default\"\n [name]=\"column.expanded ? 'tree_collapse' : 'tree_expand'\">\n </igx-icon>\n</ng-template>\n\n@if (!column.columnGroup) {\n @if (grid.hasMovableColumns) {\n <span class=\"igx-grid-th__drop-indicator-left\"></span>\n }\n <igx-pivot-row-dimension-header\n [attr.role]=\"role\"\n class=\"igx-grid-th--fw\"\n [id]=\"header ? grid.id + '_' + header.title : grid.id + '_' + column.field\"\n [ngClass]=\"column.headerClasses\"\n [ngStyle]=\"column.headerStyles | igxHeaderGroupStyle:column:grid.pipeTrigger\"\n [igxColumnMovingDrag]=\"column\"\n [ghostHost]=\"grid.outlet.nativeElement\"\n [attr.droppable]=\"true\"\n (pointerdown)=\"pointerdown($event)\"\n [igxColumnMovingDrop]=\"column\"\n [column]=\"column\"\n (keydown)=\"grid.navigation.headerNavigation($event)\"\n [style.min-width]=\"getHeaderWidthFromDimension()\"\n [style.width]=\"getHeaderWidthFromDimension()\"\n >\n </igx-pivot-row-dimension-header>\n @if (!column.columnGroup && column.resizable) {\n <span class=\"igx-grid-th__resize-handle\"\n [igxPivotResizeHandle]=\"column\"\n [igxPivotResizeHandleHeader]=\"this\"\n [attr.draggable]=\"false\"\n [style.cursor]=\"colResizingService.resizeCursor\">\n </span>\n }\n @if (grid.hasMovableColumns) {\n <span class=\"igx-grid-th__drop-indicator-right\"></span>\n }\n}\n", dependencies: [{ kind: "component", type: IgxIconComponent, selector: "igx-icon", inputs: ["ariaHidden", "family", "name", "active"] }, { kind: "component", type: IgxPivotRowDimensionHeaderComponent, selector: "igx-pivot-row-dimension-header" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: IgxColumnMovingDragDirective, selector: "[igxColumnMovingDrag]", inputs: ["igxColumnMovingDrag"] }, { kind: "directive", type: IgxColumnMovingDropDirective, selector: "[igxColumnMovingDrop]", inputs: ["igxColumnMovingDrop"] }, { kind: "directive", type: IgxPivotResizeHandleDirective, selector: "[igxPivotResizeHandle]", inputs: ["igxPivotResizeHandle", "igxPivotResizeHandleHeader"] }, { kind: "pipe", type: IgxHeaderGroupStylePipe, name: "igxHeaderGroupStyle" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxPivotRowHeaderGroupComponent, decorators: [{
type: Component,
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'igx-pivot-row-header-group', imports: [IgxIconComponent, IgxPivotRowDimensionHeaderComponent, NgClass, NgStyle, IgxColumnMovingDragDirective, IgxColumnMovingDropDirective, IgxPivotResizeHandleDirective, IgxHeaderGroupStylePipe], template: "<ng-template #defaultColumn>\n <span class=\"igx-grid-th__group-title\" [title]=\"title\">{{column.header}}</span>\n</ng-template>\n\n<ng-template #defaultCollapseIndicator>\n <igx-icon\n family=\"default\"\n [name]=\"column.expanded ? 'tree_collapse' : 'tree_expand'\">\n </igx-icon>\n</ng-template>\n\n@if (!column.columnGroup) {\n @if (grid.hasMovableColumns) {\n <span class=\"igx-grid-th__drop-indicator-left\"></span>\n }\n <igx-pivot-row-dimension-header\n [attr.role]=\"role\"\n class=\"igx-grid-th--fw\"\n [id]=\"header ? grid.id + '_' + header.title : grid.id + '_' + column.field\"\n [ngClass]=\"column.headerClasses\"\n [ngStyle]=\"column.headerStyles | igxHeaderGroupStyle:column:grid.pipeTrigger\"\n [igxColumnMovingDrag]=\"column\"\n [ghostHost]=\"grid.outlet.nativeElement\"\n [attr.droppable]=\"true\"\n (pointerdown)=\"pointerdown($event)\"\n [igxColumnMovingDrop]=\"column\"\n [column]=\"column\"\n (keydown)=\"grid.navigation.headerNavigation($event)\"\n [style.min-width]=\"getHeaderWidthFromDimension()\"\n [style.width]=\"getHeaderWidthFromDimension()\"\n >\n </igx-pivot-row-dimension-header>\n @if (!column.columnGroup && column.resizable) {\n <span class=\"igx-grid-th__resize-handle\"\n [igxPivotResizeHandle]=\"column\"\n [igxPivotResizeHandleHeader]=\"this\"\n [attr.draggable]=\"false\"\n [style.cursor]=\"colResizingService.resizeCursor\">\n </span>\n }\n @if (grid.hasMovableColumns) {\n <span class=\"igx-grid-th__drop-indicator-right\"></span>\n }\n}\n" }]
}], propDecorators: { userSelect: [{
type: HostBinding,
args: ['style.user-select']
}], rowIndex: [{
type: Input
}], dimWidth: [{
type: Input
}], rootDimension: [{
type: Input
}], header: [{
type: ViewChild,
args: [IgxPivotRowDimensionHeaderComponent]
}], headerID: [{
type: HostBinding,
args: ['attr.id']
}], title: [{
type: HostBinding,
args: ['attr.title']
}], active: [{
type: HostBinding,
args: ['class.igx-grid-th--active']
}], sortAscendingStyle: [{
type: HostBinding,
args: ['class.asc']
}], sortDescendingStyle: [{
type: HostBinding,
args: ['class.desc']
}], sortableStyle: [{
type: HostBinding,
args: ['class.igx-grid-th--sortable']
}], sortedStyle: [{
type: HostBinding,
args: ['class.igx-grid-th--sorted']
}] } });
/**
*
* For all intents & purposes treat this component as what a <thead> usually is in the default <table> element.
*
* This container holds the pivot grid header elements and their behavior/interactions.
*
* @hidden @internal
*/
class IgxPivotHeaderRowComponent extends IgxGridHeaderRowComponent {
constructor() {
super(...arguments);
this.grid = inject(IGX_GRID_BASE);
this.renderer = inject(Renderer2);
this.aggregateList = [];
this.filterDropdownDimensions = new Set();
this.filterAreaDimensions = new Set();
this._dropPos = DropPosition.AfterDropTarget;
this._subMenuPositionSettings = {
verticalStartPoint: VerticalAlignment.Bottom,
closeAnimation: undefined
};
this._subMenuOverlaySettings = {
closeOnOutsideClick: true,
modal: false,
positionStrategy: new AutoPositionStrategy(this._subMenuPositionSettings),
scrollStrategy: new AbsoluteScrollStrategy()
};
/**
* @hidden
* @internal
* Default is a single empty level since default depth is 1
*/
this.columnDimensionsByLevel = [[]];
}
get headerForOf() {
return this.headerContainers?.last;
}
get activeDescendant() {
const activeElem = this.navigation.activeNode;
if (!activeElem || !Object.keys(activeElem).length || this.grid.navigation.headerRowActiveDescendant) {
return null;
}
if (this.navigation.isRowDimensionHeaderActive) {
const activeHeader = this.grid.theadRow.rowDimensionHeaders.find(h => h.active);
if (activeHeader) {
const key = activeHeader.title ?? activeHeader.rootDimension?.memberName;
return key ? `${this.grid.id}_${key}` : null;
}
return null;
}
return super.activeDescendant;
}
/**
* @hidden @internal
*/
get isFiltersButton() {
let chipsWidth = 0;
this.filterDropdownDimensions.clear();
this.filterAreaDimensions.clear();
if (this.filterArea?.chipsList && this.filterArea.chipsList.length !== 0) {
const styles = getComputedStyle(this.pivotFilterContainer.nativeElement);
const containerPaddings = parseFloat(styles.paddingLeft) + parseFloat(styles.paddingRight);
chipsWidth += containerPaddings + (this.filtersButton && this.filterArea?.chipsList.length > 1 ? this.filtersButton.el.nativeElement.getBoundingClientRect().width : 0);
this.filterArea.chipsList.forEach(chip => {
const dim = this.grid.filterDimensions.find(x => x.memberName === chip.id);
if (dim) {
// 8 px margin between chips
const currentChipWidth = chip.nativeElement.getBoundingClientRect().width + 8;
if (chipsWidth + currentChipWidth < this.grid.pivotRowWidths) {
this.filterAreaDimensions.add(dim);
}
else {
this.filterDropdownDimensions.add(dim);
}
chipsWidth += currentChipWidth;
}
});
return this.filterDropdownDimensions.size > 0;
}
return false;
}
/**
* @hidden
* @internal
*/
get totalDepth() {
const columnDimensions = this.grid.columnDimensions;
if (columnDimensions.length === 0) {
return 1;
}
let totalDepth = columnDimensions.map(x => this.grid.data?.length > 0 ? PivotUtil.getDimensionDepth(x) + 1 : 0).reduce((acc, val) => acc + val);
if (this.grid.hasMultipleValues) {
totalDepth += 1;
}
return totalDepth;
}
/**
* @hidden
* @internal
*/
get maxContainerHeight() {
return this.totalDepth * this.grid.renderedRowHeight;
}
/**
* @hidden
* @internal
*/
get isLeafHeaderAriaHidden() {
return super.isLeafHeaderAriaHidden || this.grid.navigation.isRowHeaderActive || this.grid.navigation.isRowDimensionHeaderActive;
}
/**
* @hidden
* @internal
*/
calcHeight(col, index) {
return !col.columnGroup && col.level < this.totalDepth && col.level === index ? (this.totalDepth - col.level) * this.grid.rowHeight : this.grid.rowHeight;
}
/**
* @hidden
* @internal
*/
isDuplicateOfExistingParent(col, lvl) {
const parentCollection = lvl > 0 ? this.columnDimensionsByLevel[lvl - 1] : [];
const duplicate = parentCollection.indexOf(col) !== -1;
return duplicate;
}
/**
* @hidden
* @internal
*/
isMultiRow(col, lvl) {
const isLeaf = !col.columnGroup;
return isLeaf && lvl !== this.totalDepth - 1;
}
/**
* @hidden
* @internal
*/
populateColumnDimensionsByLevel() {
const res = [];
for (let i = 0; i < this.totalDepth; i++) {
res[i] = [];
}
const cols = this.unpinnedColumnCollection;
// populate column dimension matrix recursively
this.populateDimensionRecursively(cols.filter(x => x.level === 0), 0, res);
this.columnDimensionsByLevel = res;
}
populateDimensionRecursively(currentLevelColumns, level = 0, res) {
currentLevelColumns.forEach(col => {
if (res[level]) {
res[level].push(col);
if (col.columnGroup && col.children.length > 0) {
const visibleColumns = col.children.toArray().filter(x => !x.hidden);
this.populateDimensionRecursively(visibleColumns, level + 1, res);
}
else if (level < this.totalDepth - 1) {
for (let i = level + 1; i <= this.totalDepth - 1; i++) {
res[i].push(col);
}
}
}
});
}
/**
* @hidden
* @internal
*/
ngOnChanges(changes) {
if (changes.unpinnedColumnCollection) {
this.populateColumnDimensionsByLevel();
}
}
/**
* @hidden
* @internal
*/
onDimDragStart(event, area) {
this.cdr.detectChanges();
for (const chip of this.notificationChips) {
const parent = chip.nativeElement.parentElement;
if (area.chipsList.toArray().indexOf(chip) === -1 &&
parent.children.length > 0 &&
parent.children.item(0).id !== 'empty') {
chip.nativeElement.hidden = false;
parent.parentElement.scrollTo({ left: chip.nativeElement.offsetLeft });
}
}
}
/**
* @hidden
* @internal
*/
onDimDragEnd() {
for (const chip of this.notificationChips) {
chip.nativeElement.hidden = true;
}
}
/**
* @hidden
* @internal
*/
getAreaHeight(area) {
const chips = area.chipsList;
return chips && chips.length > 0 ? chips.first.nativeElement.offsetHeight : 0;
}
/**
* @hidden
* @internal
*/
rowRemoved(event) {
const row = this.grid.pivotConfiguration.rows.find(x => x.memberName === event.owner.id);
this.grid.toggleDimension(row);
}
/**
* @hidden
* @internal
*/
columnRemoved(event) {
const col = this.grid.pivotConfiguration.columns.find(x => x.memberName === event.owner.id);
this.grid.toggleDimension(col);
}
/**
* @hidden
* @internal
*/
valueRemoved(event) {
const value = this.grid.pivotConfiguration.values.find(x => x.member === event.owner.id || x.displayName === event.owner.id);
this.grid.toggleValue(value);
}
/**
* @hidden
* @internal
*/
filterRemoved(event) {
const filter = this.grid.pivotConfiguration.filters.find(x => x.memberName === event.owner.id);
this.grid.toggleDimension(filter);
if (this.filterDropdownDimensions.size > 0) {
this.onFiltersAreaDropdownClick({ target: this.filtersButton.el.nativeElement }, undefined, false);
}
else {
this.grid.filteringService.hideESF();
}
}
onFiltersSelectionChanged(event) {
this.dropdownChips.chipsList.forEach(chip => {
if (chip.id !== event.owner.id) {
chip.selected = false;
}
});
this.onFiltersAreaDropdownClick({ target: this.filtersButton.el.nativeElement }, this.grid.filterDimensions.find(dim => dim.memberName === event.owner.id), false);
}
/**
* @hidden
* @internal
*/
onFilteringIconPointerDown(event) {
event.stopPropagation();
event.preventDefault();
}
/**
* @hidden
* @internal
*/
onFilteringIconClick(event, dimension) {
event.stopPropagation();
event.preventDefault();
const dim = dimension;
const col = this.grid.dimensionDataColumns.find(x => x.field === dim.memberName || x.field === dim.member);
this.grid.filteringService.toggleFilterDropdown(event.target, col);
}
/**
* @hidden
* @internal
*/
onSummaryClick(eventArgs, value, dropdown, chip) {
this._subMenuOverlaySettings.target = eventArgs.currentTarget;
this.updateDropDown(value, dropdown, chip);
}
/**
* @hidden @internal
*/
onFiltersAreaDropdownClick(event, dimension, shouldReattach = true) {
const dim = dimension || this.filterDropdownDimensions.values().next().value;
const col = this.grid.dimensionDataColumns.find(x => x.field === dim.memberName || x.field === dim.member);
if (shouldReattach) {
this.dropdownChips.chipsList.forEach(chip => {
chip.selected = false;
});
this.dropdownChips.chipsList.first.selected = true;
}
this.grid.filteringService.toggleFiltersESF(this.esf, event.target, col, shouldReattach);
}
/**
* @hidden
* @internal
*/
onAggregationChange(event) {
if (!this.isSelected(event.newSelection.value)) {
this.value.aggregate = event.newSelection.value;
const isSingleValue = this.grid.values.length === 1;
PivotUtil.updateColumnTypeByAggregator(this.grid.columns, this.value, isSingleValue);
this.grid.pipeTrigger++;
}
}
/**
* @hidden
* @internal
*/
isSelected(val) {
return this.value.aggregate.key === val.key;
}
/**
* @hidden
* @internal
*/
onChipSort(_event, dimension) {
if (dimension.sortable === undefined || dimension.sortable) {
const startDirection = dimension.sortDirection || SortingDirection.None;
const direction = startDirection + 1 > SortingDirection.Desc ?
SortingDirection.None : startDirection + 1;
this.grid.sortDimension(dimension, direction);
}
}
/**
* @hidden
* @internal
*/
onDimDragOver(event, dimension) {
if (!event.dragChip || !event.dragChip.data?.pivotArea)
return;
const typeMismatch = dimension !== undefined ? this.grid.pivotConfiguration.values.find(x => x.member === event.dragChip.id
|| x.displayName === event.dragChip.id) :
!this.grid.pivotConfiguration.values.find(x => x.member === event.dragChip.id || x.displayName === event.dragChip.id);
if (typeMismatch) {
// cannot drag between dimensions and value
return;
}
// if we are in the left half of the chip, drop on the left
// else drop on the right of the chip
const clientRect = event.owner.nativeElement.getBoundingClientRect();
const pos = clientRect.width / 2;
this._dropPos = event.originalEvent.offsetX > pos ? DropPosition.AfterDropTarget : DropPosition.BeforeDropTarget;
if (this._dropPos === DropPosition.AfterDropTarget) {
event.owner.nativeElement.previousElementSibling.style.visibility = 'hidden';
event.owner.nativeElement.nextElementSibling.style.visibility = '';
}
else {
event.owner.nativeElement.nextElementSibling.style.visibility = 'hidden';
event.owner.nativeElement.previousElementSibling.style.visibility = '';
}
}
/**
* @hidden
* @internal
*/
onDimDragLeave(event) {
event.owner.nativeElement.previousElementSibling.style.visibility = 'hidden';
event.owner.nativeElement.nextElementSibling.style.visibility = 'hidden';
this._dropPos = DropPosition.AfterDropTarget;
}
/**
* @hidden
* @internal
*/
onAreaDragLeave(event, area) {
const dataChips = area.chipsList.toArray().filter(x => this.notificationChips.toArray().indexOf(x) === -1);
dataChips.forEach(element => {
if (element.nativeElement.previousElementSibling) {
element.nativeElement.previousElementSibling.style.visibility = 'hidden';
}
if (element.nativeElement.nextElementSibling) {
element.nativeElement.nextElementSibling.style.visibility = 'hidden';
}
});
}
/**
* @hidden
* @internal
*/
onValueDrop(event, area) {
if (!(event.dragChip && event.dragChip.data?.pivotArea) && !(event.dragData?.chip && !!event.dragData.chip.data.pivotArea))
return;
//values can only be reordered
const values = this.grid.pivotConfiguration.values;
const dragId = event.dragChip?.id || event.dragData?.chip.id;
const chipsArray = area.chipsList.toArray();
let chipIndex = chipsArray.indexOf(event.owner) !== -1 ? chipsArray.indexOf(event.owner) : chipsArray.length;
chipIndex = this._dropPos === DropPosition.AfterDropTarget ? chipIndex + 1 : chipIndex;
const value = values.find(x => x.member === dragId || x.displayName === dragId);
if (value) {
const dragChipIndex = chipsArray.indexOf(event.dragChip || event.dragData.chip);
this.grid.moveValue(value, dragChipIndex >= chipIndex ? chipIndex : chipIndex - 1);
}
}
/**
* @hidden
* @internal
*/
onDimDrop(event, area, dimensionType) {
if (!(event.dragChip && event.dragChip.data?.pivotArea) && !(event.dragData?.chip && !!event.dragData.chip.data.pivotArea))
return;
const dragId = event.dragChip?.id || event.dragData?.chip.id;
const currentDim = this.grid.getDimensionsByType(dimensionType);
const chipsArray = area.chipsList.toArray();
const chip = chipsArray.find(x => x.id === dragId);
const isNewChip = chip === undefined;
const isReorder = event.owner.id !== undefined;
//const chipIndex = chipsArray.indexOf(event.owner) !== -1 ? chipsArray.indexOf(event.owner) : chipsArray.length;
const chipIndex = currentDim.findIndex(x => x.memberName === event.owner.id) !== -1 ?
currentDim.findIndex(x => x.memberName === event.owner.id) : currentDim.length;
const targetIndex = this._dropPos === DropPosition.AfterDropTarget ? chipIndex + 1 : chipIndex;
if (isNewChip) {
// chip moved from an external collection
const dim = this.grid.allDimensions.find(x => x && x.memberName === dragId);
if (!dim) {
// you have dragged something that is not a dimension
return;
}
this.grid.moveDimension(dim, dimensionType, targetIndex);
}
else if (isReorder) {
// chip from same collection, reordered.
const newDim = currentDim.find(x => x.memberName === dragId);
const dragChipIndex = currentDim.findIndex(x => x.memberName === dragId);
this.grid.moveDimension(newDim, dimensionType, dragChipIndex > chipIndex ? targetIndex : targetIndex - 1);
}
this.grid.pipeTrigger++;
this.grid.dimensionsChange.emit({ dimensions: currentDim, dimensionCollectionType: dimensionType });
// clean states
this.onDimDragEnd();
this.onAreaDragLeave(event, area);
}
updateDropDown(value, dropdown, chip) {
this.value = value;
dropdown.width = chip.nativeElement.clientWidth + 'px';
this.aggregateList = PivotUtil.getAggregateList(value, this.grid);
this.cdr.detectChanges();
dropdown.open(this._subMenuOverlaySettings);
}
getRowDimensionColumn(dim) {
return this.grid.dimensionDataColumns ? this.grid.dimensionDataColumns.find((col) => col.field === dim.memberName) : null;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxPivotHeaderRowComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.2", type: IgxPivotHeaderRowComponent, isStandalone: true, selector: "igx-pivot-header-row", host: { properties: { "attr.aria-activedescendant": "this.activeDescendant" } }, viewQueries: [{ propertyName: "esf", first: true, predicate: ["esf"], descendants: true }, { propertyName: "filterArea", first: true, predicate: ["filterAreaHidden"], descendants: true }, { propertyName: "filtersButton", first: true, predicate: ["filterIcon"], descendants: true }, { propertyName: "dropdownChips", first: true, predicate: ["dropdownChips"], descendants: true }, { propertyName: "pivotFilterContainer", first: true, predicate: ["pivotFilterContainer"], descendants: true }, { propertyName: "pivotRowContainer", first: true, predicate: ["pivotRowContainer"], descendants: true }, { propertyName: "notificationChips", predicate: ["notifyChip"], descendants: true }, { propertyName: "headerContainers", predicate: ["headerVirtualContainer"], descendants: true, read: IgxGridForOfDirective }, { propertyName: "rowDimensionHeaders", predicate: ["rowDimensionHeaders"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div>\n <div class=\"igx-grid-thead__wrapper igx-grid-thead__wrapper--pivot\" role=\"row\" [style.width.px]=\"width\">\n <div class=\"igx-grid__tr\" role=\"row\" [style.width.px]=\"width\">\n <div class='igx-grid__tr-pivot--filter-container'>\n @if (grid.pivotUI.showConfiguration) {\n <div #pivotFilterContainer\n class=\"igx-grid__tr-pivot igx-grid__tr-pivot--filter\" [style.min-width.px]=\"grid.pivotRowWidths - 1\"\n [style.max-width.px]=\"grid.pivotRowWidths - 1\" (igxDragLeave)=\"onAreaDragLeave($event, filterArea)\"\n igxDrop (dropped)=\"onDimDrop($event, filterArea, 2)\" (pointerdown)=\"$event.preventDefault()\">\n <!-- Filter area -->\n <igx-chips-area #filterArea droppable='true'>\n @if (grid.filterDimensions.length === 0) {\n <span id='empty' igxDrop (dropped)=\"onDimDrop($event, filterArea, 2)\"\n class='igx-grid__pivot-empty-chip-area'>{{grid.resourceStrings.igx_grid_pivot_empty_filter_drop_area}}</span>\n }\n @for (filter of this.filterAreaDimensions; track filter; let last = $last) {\n <span class=\"igx-grid__tr-pivot--chip_drop_indicator\"\n [style.height.px]='getAreaHeight(filterArea)'></span>\n <igx-chip [id]=\"filter.memberName\" [draggable]=\"true\" [data]=\"{ pivotArea: 'filter' }\"\n [removable]=\"true\" (remove)=\"filterRemoved($event)\" (dragOver)=\"onDimDragOver($event, 2)\"\n (dragLeave)=\"onDimDragLeave($event)\" (dragDrop)=\"onDimDrop($event, filterArea, 2)\"\n (moveStart)='onDimDragStart($event, filterArea)' (moveEnd)='onDimDragEnd()'>\n <igx-icon\n family=\"default\"\n name=\"filter_list\"\n igxPrefix\n (pointerdown)='onFilteringIconPointerDown($event)'\n (click)='onFilteringIconClick($event, filter)'>\n </igx-icon>\n {{filter.displayName || filter.memberName}}\n </igx-chip>\n @if (last) {\n <span class=\"igx-grid__tr-pivot--chip_drop_indicator\"\n [style.height.px]='getAreaHeight(filterArea)'></span>\n }\n }\n <igx-chip igxDrop (dragDrop)=\"onDimDrop($event, filterArea, 2)\" #notifyChip [hidden]='true'>\n {{grid.resourceStrings.igx_grid_pivot_filter_drop_chip}}\n </igx-chip>\n </igx-chips-area>\n @if (isFiltersButton && grid.filterDimensions.length !== 0) {\n <div class=\"igx-grid__pivot-filter-toggle\">\n <igx-icon\n family=\"default\"\n name=\"filter_list\"\n #filterIcon\n (pointerdown)='onFilteringIconPointerDown($event)'\n (click)='onFiltersAreaDropdownClick($event)'>\n </igx-icon>\n <igx-badge value=\"{{this.filterDropdownDimensions.size}}\"></igx-badge>\n </div>\n }\n </div>\n }\n <div class='igx-grid__tr-pivot--drop-row-area'>\n @if (grid.pivotUI.showConfiguration && grid.pivotUI.showRowHeaders) {\n <div #pivotRowContainer [style.width.px]=\"grid.pivotRowWidths - 1\"\n class=\"igx-grid__tr-pivot igx-grid__tr-pivot--small-row-area\" igxDrop\n (igxDragLeave)=\"onAreaDragLeave($event, rowArea)\"\n (dropped)=\"onDimDrop($event, rowArea, 0)\">\n <igx-chips-area #rowArea droppable='true'>\n @if (grid.rowDimensions.length === 0) {\n <span id='empty' igxDrop (dropped)=\"onDimDrop($event, rowArea, 0)\"\n class='igx-grid__pivot-empty-chip-area'>{{grid.resourceStrings.igx_grid_pivot_empty_row_drop_area}}</span>\n }\n @for (row of grid.rowDimensions; track row.memberName; let last = $last) {\n <span class=\"igx-grid__tr-pivot--chip_drop_indicator\"\n [style.height.px]='getAreaHeight(rowArea)'></span>\n <igx-chip [draggable]=\"true\" [id]=\"row.memberName\" [data]=\"{ pivotArea: 'row' }\"\n [removable]=\"true\" (remove)=\"rowRemoved($event)\" (dragLeave)=\"onDimDragLeave($event)\"\n (dragDrop)=\"onDimDrop($event, rowArea, 0)\" (dragOver)=\"onDimDragOver($event, 0)\"\n (moveStart)='onDimDragStart($event, rowArea)' (moveEnd)='onDimDragEnd()'\n (click)=\"onChipSort($event, row)\">\n <igx-icon igxPrefix family=\"default\" name=\"table_rows\"></igx-icon>\n <igx-icon\n family=\"default\"\n name=\"filter_list\"\n igxPrefix\n (pointerdown)='onFilteringIconPointerDown($event)'\n (click)='onFilteringIconClick($event, row)'>\n </igx-icon>\n {{ row.displayName || row.memberName}}\n @if (row.sortDirection) {\n <igx-icon\n family=\"default\"\n [name]=\"row.sortDirection < 2 ? 'sort_asc' : 'sort_desc'\"\n igxSuffix>\n </igx-icon>\n }\n </igx-chip>\n @if (last) {\n <span class=\"igx-grid__tr-pivot--chip_drop_indicator\"\n [style.height.px]='getAreaHeight(rowArea)'></span>\n }\n }\n <igx-chip igxDrop (dragDrop)=\"onDimDrop($event, rowArea, 0)\" #notifyChip [hidden]='true'>\n {{grid.resourceStrings.igx_grid_pivot_row_drop_chip}}\n </igx-chip>\n </igx-chips-area>\n </div>\n }\n </div>\n </div>\n\n <div class=\"igx-grid__tr-pivot-group\">\n @if (grid.pivotUI.showConfiguration) {\n <div #pivotColumnContainer class=\"igx-grid__tr-pivot\"\n (dropped)=\"onDimDrop($event, colArea, 1)\" igxDrop (igxDragLeave)=\"onAreaDragLeave($event, colArea)\">\n <!-- Columns area -->\n <igx-chips-area #colArea droppable='true'>\n @if (grid.columnDimensions.length === 0) {\n <span id='empty' (dropped)=\"onDimDrop($event, colArea, 1)\" igxDrop\n class='igx-grid__pivot-empty-chip-area'>\n {{grid.resourceStrings.igx_grid_pivot_empty_column_drop_area}}</span>\n }\n @for (col of grid.columnDimensions; track col.memberName; let last = $last) {\n <span class=\"igx-grid__tr-pivot--chip_drop_indicator\"\n [style.height.px]='getAreaHeight(colArea)'></span>\n <igx-chip [draggable]=\"true\" [id]=\"col.memberName\" [data]=\"{ pivotArea: 'column' }\"\n [removable]=\"true\" (remove)=\"columnRemoved($event)\" (dragOver)=\"onDimDragOver($event, 1)\"\n (dragLeave)=\"onDimDragLeave($event)\" (dragDrop)=\"onDimDrop($event, colArea, 1)\"\n (moveStart)='onDimDragStart($event, colArea)' (moveEnd)='onDimDragEnd()'\n (click)=\"onChipSort($event, col)\">\n <igx-icon\n family=\"default\"\n