@progress/kendo-angular-pivotgrid
Version:
PivotGrid package for Angular
751 lines (722 loc) • 41.6 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the project root for more information
*-------------------------------------------------------------------------------------------*/
import { ChangeDetectorRef, Component, EventEmitter, HostBinding, Input, NgZone, Output, ViewChild } from '@angular/core';
import { ConfiguratorNavigation } from '@progress/kendo-pivotgrid-common';
import { CheckDirective, ExpandDirective, TreeViewComponent } from '@progress/kendo-angular-treeview';
import { PivotGridDataService } from '../data-binding/pivotgrid-data.service';
import { ConfiguratorService } from './configurator.service';
import { DropCueService } from './drop-cue.service';
import { from, of, Subscription } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
import { clone, swapItems } from '../util';
import { LocalizationService } from '@progress/kendo-angular-l10n';
import { SinglePopupService } from './chip-menu/single-popup.service';
import { ButtonComponent, ChipComponent, ChipListComponent } from '@progress/kendo-angular-buttons';
import { ChipMenuComponent } from './chip-menu/chip-menu.component';
import { ChipKeyboardNavigationDirective } from './chip-kb-nav.directive';
import { DraggableChipDirective } from './draggable.directive';
import { DropTargetDirective } from './drop-target.directive';
import { NgClass, NgStyle, NgIf, NgTemplateOutlet, NgFor } from '@angular/common';
import { DraggableDirective } from '@progress/kendo-angular-common';
import * as i0 from "@angular/core";
import * as i1 from "../data-binding/pivotgrid-data.service";
import * as i2 from "@progress/kendo-angular-l10n";
import * as i3 from "./configurator.service";
/**
* @hidden
* Represents the Kendo UI PivotGrid Configurator component for Angular.
*/
export class PivotGridConfiguratorComponent {
dataService;
localization;
configuratorService;
cdr;
zone;
hostClass = true;
hostAriaRole = 'dialog';
get headerTextId() {
return `k-pivotgrid-${this.dataService.pivotGridId}-configurator-header`;
}
orientation = 'vertical';
sort = new Array();
filter;
navigation;
close = new EventEmitter();
treeView;
columnsList;
rowsList;
originalState;
state;
fields;
checked = [];
get isHorizontal() {
return this.orientation === 'horizontal';
}
subs = new Subscription();
/**
* A function which determines if a specific node has child nodes.
*/
hasChildren = (node) => !('hierarchyUniqueName' in node) && !('aggregator' in node);
constructor(dataService, localization, configuratorService, cdr, zone) {
this.dataService = dataService;
this.localization = localization;
this.configuratorService = configuratorService;
this.cdr = cdr;
this.zone = zone;
this.configuratorService.configuratorInstance = this;
}
ngOnInit() {
this.subs.add(this.dataService.fields
.subscribe(res => {
this.fields = res;
}));
this.subs.add(this.dataService.configuredFields
.subscribe(res => {
const normalizedState = clone({ ...this.dataService.state, dragItem: res.dragItem, dropTarget: res.dropTarget, dropZone: res.dropZone, dropDirection: res.dropDirection });
this.originalState = normalizedState;
this.setState(normalizedState);
this.setChecked();
}));
this.subs.add(this.configuratorService.configuratorStateChange
.subscribe(res => {
this.state = res;
this.dataService.state = {
columnAxes: res.columnAxes,
rowAxes: res.rowAxes,
measureAxes: res.measureAxes,
sort: res.sort,
filter: res.filter
};
this.cdr.detectChanges();
}));
}
ngAfterViewInit() {
this.treeView.focus();
}
ngOnDestroy() {
this.subs.unsubscribe();
}
ngOnChanges(changes) {
if (changes['orientation']) {
this.configuratorService.orientation = this.orientation;
}
}
getName(name) {
return name.toString();
}
contentLabelId(section) {
return `k-pivotgrid-${this.dataService.pivotGridId}-configurator-${section}`;
}
setState(state) {
this.dataService.state = {
columnAxes: state.columnAxes,
rowAxes: state.rowAxes,
measureAxes: state.measureAxes,
sort: state.sort,
filter: state.filter
};
this.state = this.configuratorService.state = state;
this.cdr.detectChanges();
}
onReorder(ev, name, item) {
const currentCollection = this.state[`${name}Axes`];
const itemIndex = currentCollection.indexOf(item);
switch (ev.direction) {
case 'right':
if (itemIndex !== currentCollection.length - 1) {
this.swapChips(currentCollection, itemIndex, ev.direction, name);
}
break;
case 'left':
if (itemIndex !== 0) {
this.swapChips(currentCollection, itemIndex, ev.direction, name);
ev.sender.focus();
}
break;
case 'up':
if (name === 'row') {
this.moveChip(currentCollection, item, itemIndex, name);
}
break;
case 'down':
if (name === 'column') {
this.moveChip(currentCollection, item, itemIndex, name);
}
break;
default:
break;
}
}
/**
* Returns the localized message for a given token
*/
messageFor(localizationToken) {
return this.localization.get(localizationToken);
}
/**
* Retrieves the 'Columns' section item names
*/
get columnHierarchies() {
return this.extractDefaultFields(this.dataService.state.columnAxes);
}
/**
* Retrieves the 'Rows' section item names
*/
get rowHierarchies() {
return this.extractDefaultFields(this.dataService.state.rowAxes);
}
/**
* Retrieves the 'Value' section item names
*/
get measureHierarchies() {
return this.extractDefaultFields(this.dataService.state.measureAxes);
}
/**
* Updates the respective axis configuration of the current state
* when a chip is deleted from the UI
*/
onChipRemove(ev, item, section) {
const filteredItems = this.dataService.state[`${section}Axes`].filter(descriptor => descriptor !== item);
this.dataService.state[`${section}Axes`] = filteredItems;
const newState = { ...this.state, ...this.dataService.state };
this.checked = this.checked.filter(checkedItem => checkedItem.uniqueName !== item.name[0]);
const targetIndex = this.navigation?.elements.indexOf(ev.sender.element.nativeElement);
this.setState(newState);
if (!this.navigation) {
return;
}
this.zone.runOutsideAngular(() => setTimeout(() => this.navigation.focusElement(this.navigation.elements[targetIndex - 1], this.navigation.elements[targetIndex])));
}
/**
* Constructs an array with all selected fields.
* @param fields - used for when child nodes are loaded on demand.
* Child nodes are concatinated to the root level nodes.
*/
setChecked(fields = []) {
const allFields = [...this.fields, ...fields];
const checked = this.getFieldsFlatMap(allFields).filter((f) => [
...this.columnHierarchies,
...this.rowHierarchies,
...this.measureHierarchies
].some((h) => (h === f.uniqueName || h === f.defaultHierarchy)));
this.checked = checked;
}
checkItemBy = (context) => {
return context.dataItem;
};
/**
* Determines if a checkbox should be rendered.
*/
isSelectable(node) {
const hasChildren = !('hierarchyUniqueName' in node) && !('aggregator' in node);
return !((!hasChildren && !node.aggregator && !node.measure)
|| (node.type === 2)
|| node.uniqueName === '[KPIs]');
}
/**
* A function which provides the child nodes for a given parent node.
*/
children = (node) => {
if (this.dataService.directive.type === 'olap') {
const observable = from(this.dataService.directive.fetchChildren(node, this.fields));
return observable.pipe(mergeMap(value => of(value)));
}
return of(node.children);
};
/**
* Check if the newly loaded child nodes have checked items.
* (Only for OLAP data-binding directive)
*/
handleChildrenLoaded(event) {
if (this.dataService.directive.type === 'local') {
return;
}
const fields = event.children.map(item => item.dataItem);
this.setChecked(fields);
}
handleCheckedChange(event) {
const itemIndex = this.checked.findIndex(checkedItem => checkedItem.uniqueName === event.item.dataItem.uniqueName);
this.checked.splice(itemIndex, 1);
const action = {
type: 'PIVOT_CONFIGURATOR_ACTION_TOGGLE_SELECTION',
payload: event.item.dataItem
};
this.configuratorService.parseConfiguratorState(action);
}
onTreeViewSelect(ev) {
const closestItem = ev.target.closest('.k-treeview-item');
if (closestItem) {
closestItem.querySelector('.k-checkbox')?.click();
}
}
onTreeViewEscape(ev) {
ev.stopImmediatePropagation();
this.close.emit();
}
handleSubmit() {
this.dataService.configuratorFieldChange.emit(this.dataService.state);
}
/**
* Reset the configurator to the last saved state
*/
handleReset() {
this.setState(clone(this.originalState));
this.setChecked();
}
/**
* Flattens all available fields.
*/
getFieldsFlatMap(nodes = []) {
let result = [...nodes];
(nodes || []).forEach((child) => {
result = result.concat(this.getFieldsFlatMap(child.children));
});
return result;
}
/**
* Creates an array containing only the field names, e.g. '[Date].[Calendar]' or 'Product'
*/
extractDefaultFields(columns = []) {
const result = new Set();
columns.forEach((column) => {
result.add(String(column.name));
});
return Array.from(result);
}
/**
* Swaps chips within the same ChipList
*/
swapChips(collection, itemIndex, direction, name) {
const targetIndex = itemIndex + (direction === 'right' ? 1 : -1);
swapItems(collection, itemIndex, targetIndex);
this.dataService.state[`${name}Axes`] = collection;
const newState = { ...this.state, ...this.dataService.state };
this.setState(newState);
this.cdr.detectChanges();
}
/**
* Moves a chip from one ChipList to another
*/
moveChip(collection, item, itemIndex, name) {
collection.splice(itemIndex, 1);
const targetCollectionName = name === 'row' ? 'column' : 'row';
const axes = this.state[`${targetCollectionName}Axes`];
axes.push(item);
this.dataService.state[`${name}Axes`] = collection;
this.dataService.state[targetCollectionName] = axes;
const newState = { ...this.state, ...this.dataService.state };
this.setState(newState);
this.cdr.detectChanges();
this[`${targetCollectionName}sList`]?.chips.last.focus();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PivotGridConfiguratorComponent, deps: [{ token: i1.PivotGridDataService }, { token: i2.LocalizationService }, { token: i3.ConfiguratorService }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: PivotGridConfiguratorComponent, isStandalone: true, selector: "kendo-pivotgrid-configurator", inputs: { orientation: "orientation", sort: "sort", filter: "filter", navigation: "navigation" }, outputs: { close: "close" }, host: { properties: { "class.k-pivotgrid-configurator": "this.hostClass", "attr.role": "this.hostAriaRole", "attr.aria-labelledby": "this.headerTextId" } }, providers: [
ConfiguratorService,
DropCueService,
SinglePopupService
], viewQueries: [{ propertyName: "treeView", first: true, predicate: TreeViewComponent, descendants: true }, { propertyName: "columnsList", first: true, predicate: ["columnsChiplist"], descendants: true }, { propertyName: "rowsList", first: true, predicate: ["rowsChiplist"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
<div
class="k-pivotgrid-configurator-panel k-pivotgrid-configurator-push"
[ngClass]="{
'k-pivotgrid-configurator-horizontal': isHorizontal,
'k-pivotgrid-configurator-vertical': !isHorizontal
}"
>
<div class="k-pivotgrid-configurator-header">
<div
[id]="headerTextId"
class="k-pivotgrid-configurator-header-text">{{messageFor('configuratorHeaderText')}}</div>
</div>
<div class="k-pivotgrid-configurator-content">
<div class="k-form k-form-md" [class.k-form-horizontal]="isHorizontal" [class.k-form-vertical]="!isHorizontal" role="form">
<div class="k-form-field-wrapper" [ngStyle]="isHorizontal ? {'padding-left': 0 } : null">
<div class="k-form-field" [style]="'padding-top: 1em; margin-top: 0;'" [ngStyle]="isHorizontal ? {'padding-top': 0, 'padding-left': '16px' } : null">
<span [id]="contentLabelId('fields')" class="k-label">{{messageFor('configuratorFieldsText')}}</span>
</div>
<div class="k-form-field" [style]="'padding-top: 1em; margin-top: 0;'" [ngStyle]="isHorizontal ? {'padding-top': 0, 'padding-left': '16px' } : null">
<div class="k-fields-list-wrapper">
<kendo-treeview
#treeview
[attr.aria-labelledby]="headerTextId + ' ' + contentLabelId('fields')"
(focus)="treeview.focus()"
[nodes]="fields"
textField="caption"
[children]="children"
[hasChildren]="hasChildren"
kendoTreeViewCheckable
[hasCheckbox]="isSelectable"
[(checkedKeys)]="checked"
[checkBy]="checkItemBy"
(checkedChange)="handleCheckedChange($event)"
kendoTreeViewExpandable
(childrenLoaded)="handleChildrenLoaded($event)"
(keydown.space)="onTreeViewSelect($event)">
</kendo-treeview>
</div>
</div>
</div>
<div *ngIf="isHorizontal; else verticalTemplate" class="k-form-field-wrapper" [ngStyle]="isHorizontal ? {'padding-left': 0 } : null">
<ng-container *ngTemplateOutlet="verticalTemplate"></ng-container>
</div>
<ng-template #verticalTemplate>
<div class="k-form-field" kendoDropTarget axes="columnAxes" [style]="'padding-top: 1em; margin-top: 0;'" [ngStyle]="isHorizontal ? {'padding-top': 0, 'padding-left': '16px' } : null">
<span [id]="contentLabelId('columns')" class="k-label">{{messageFor('configuratorColumnsText')}}</span>
</div>
<kendo-chiplist
*ngIf="state.columnAxes && state.columnAxes.length; else noColumnAxes"
[navigable]="false"
#columnsChiplist
kendoDropTarget
class="k-column-fields"
axes="columnAxes"
[style.width.%]="100"
[attr.aria-labelledby]="headerTextId + ' ' + contentLabelId('columns')"
[ngStyle]="isHorizontal ? {'padding-top': 0, 'padding-left': '16px' } : null"
>
<ng-container *ngFor="let item of state.columnAxes">
<kendo-chip *ngIf="item.name.length === 1"
#chip
kendoChipDraggable
kendoDraggable
kendoDropTarget
kendoChipKeyboardNavigation
[item]="item"
[label]="getName(item.name)"
axes="columnAxes"
[removable]="true"
[hasMenu]="true"
(menuToggle)="chipMenuColumns.toggle($event)"
(remove)="onChipRemove($event, item, 'column')"
(reorder)="onReorder($event, 'column', item)"
>
<kendo-pivot-chip-menu
#chipMenuColumns
[chip]="item"
[anchor]="chip"
></kendo-pivot-chip-menu>
</kendo-chip>
</ng-container>
</kendo-chiplist>
<ng-template #noColumnAxes>
<div class="k-settings-description" kendoDropTarget axes="columnAxes">{{messageFor('configuratorEmptyColumnsText')}}</div>
</ng-template>
<div class="k-form-field" kendoDropTarget axes="rowAxes" [style]="'padding-top: 1em; margin-top: 0;'" [ngStyle]="isHorizontal ? {'padding-top': 0, 'padding-left': '16px' } : null">
<span [id]="contentLabelId('rows')" class="k-label">{{messageFor('configuratorRowsText')}}</span>
</div>
<kendo-chiplist
*ngIf="state.rowAxes && state.rowAxes.length; else noRowAxes"
[navigable]="false"
#rowsChiplist
kendoDropTarget
class="k-row-fields"
axes="rowAxes"
[attr.aria-labelledby]="headerTextId + ' ' + contentLabelId('rows')"
[ngStyle]="isHorizontal ? {'padding-top': 0, 'padding-left': '16px' } : null"
[style.width.%]="100"
>
<ng-container *ngFor="let item of state.rowAxes">
<kendo-chip *ngIf="item.name.length === 1"
#chip
kendoChipDraggable
kendoDraggable
kendoDropTarget
kendoChipKeyboardNavigation
[item]="item"
[label]="getName(item.name)"
axes="rowAxes"
[removable]="true"
[hasMenu]="true"
(menuToggle)="chipMenuRows.toggle($event)"
(remove)="onChipRemove($event, item, 'row')"
(reorder)="onReorder($event, 'row', item)"
>
<kendo-pivot-chip-menu
#chipMenuRows
[chip]="item"
[anchor]="chip"
></kendo-pivot-chip-menu>
</kendo-chip>
</ng-container>
</kendo-chiplist>
<ng-template #noRowAxes>
<div class="k-settings-description" kendoDropTarget axes="rowAxes">{{messageFor('configuratorEmptyRowsText')}}</div>
</ng-template>
</ng-template>
<div *ngIf="isHorizontal; else verticalMeasuresTemplate" class="k-form-field-wrapper" [ngStyle]="isHorizontal ? {'padding-left': 0 } : null" >
<ng-container *ngTemplateOutlet="verticalMeasuresTemplate"></ng-container>
</div>
<ng-template #verticalMeasuresTemplate>
<div class="k-form-field" kendoDropTarget axes="measureAxes" [style]="'padding-top: 1em; margin-top: 0;'" [ngStyle]="isHorizontal ? {'padding-top': 0, 'padding-left': '16px' } : null">
<span [id]="contentLabelId('values')" class="k-label">{{messageFor('configuratorValuesText')}}</span>
</div>
<kendo-chiplist
*ngIf="state.measureAxes && state.measureAxes.length; else noMeasureAxes"
[navigable]="false"
kendoDropTarget
class="k-filter-fields"
axes="measureAxes"
[attr.aria-labelledby]="headerTextId + ' ' + contentLabelId('values')"
[ngStyle]="isHorizontal ? {'padding-top': 0, 'padding-left': '16px' } : null"
[style.width.%]="100"
>
<kendo-chip *ngFor="let item of state.measureAxes"
#chip
kendoChipDraggable
kendoDraggable
kendoDropTarget
kendoChipKeyboardNavigation
[item]="item"
[label]="getName(item.name)"
axes="measureAxes"
[removable]="true"
[hasMenu]="true"
(menuToggle)="chipMenuValues.toggle($event)"
(remove)="onChipRemove($event, item, 'measure')"
(reorder)="onReorder($event, 'measure', item)"
>
<kendo-pivot-chip-menu
#chipMenuValues
[chip]="item"
[anchor]="chip"
></kendo-pivot-chip-menu>
</kendo-chip>
</kendo-chiplist>
<ng-template #noMeasureAxes>
<div class="k-settings-description" kendoDropTarget axes="measureAxes">{{messageFor('configuratorEmptyMeasuresText')}}</div>
</ng-template>
</ng-template>
</div>
</div>
<div class="k-pivotgrid-configurator-actions k-actions k-actions-end k-actions-horizontal">
<button kendoButton type="button" (click)="handleReset()">{{messageFor('configuratorCancelButtonText')}}</button>
<button kendoButton themeColor="primary" type="button" (click)="handleSubmit()">{{messageFor('configuratorApplyButtonText')}}</button>
</div>
</div>
`, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: TreeViewComponent, selector: "kendo-treeview", inputs: ["filterInputPlaceholder", "expandDisabledNodes", "animate", "nodeTemplate", "loadMoreButtonTemplate", "trackBy", "nodes", "textField", "hasChildren", "isChecked", "isDisabled", "hasCheckbox", "isExpanded", "isSelected", "isVisible", "navigable", "children", "loadOnDemand", "filterable", "filter", "size", "disableParentNodesOnly"], outputs: ["childrenLoaded", "blur", "focus", "expand", "collapse", "nodeDragStart", "nodeDrag", "filterStateChange", "nodeDrop", "nodeDragEnd", "addItem", "removeItem", "checkedChange", "selectionChange", "filterChange", "nodeClick", "nodeDblClick"], exportAs: ["kendoTreeView"] }, { kind: "directive", type: ExpandDirective, selector: "[kendoTreeViewExpandable]", inputs: ["isExpanded", "expandBy", "expandOnFilter", "expandedKeys"], outputs: ["expandedKeysChange"] }, { kind: "directive", type: CheckDirective, selector: "[kendoTreeViewCheckable]", inputs: ["isChecked", "checkBy", "checkedKeys", "kendoTreeViewCheckable"], outputs: ["checkedKeysChange"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: DropTargetDirective, selector: "[kendoDropTarget]", inputs: ["item", "axes"] }, { kind: "component", type: ChipListComponent, selector: "kendo-chiplist, kendo-chip-list", inputs: ["selection", "size", "role", "navigable"], outputs: ["selectedChange", "remove"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: ChipComponent, selector: "kendo-chip", inputs: ["label", "icon", "svgIcon", "iconClass", "avatarSettings", "selected", "removable", "removeIcon", "removeSvgIcon", "hasMenu", "menuIcon", "menuSvgIcon", "disabled", "size", "rounded", "fillMode", "themeColor"], outputs: ["remove", "menuToggle", "contentClick"] }, { kind: "directive", type: DraggableChipDirective, selector: "[kendoChipDraggable]", inputs: ["item"] }, { kind: "directive", type: DraggableDirective, selector: "[kendoDraggable]", inputs: ["enableDrag"], outputs: ["kendoPress", "kendoDrag", "kendoRelease"] }, { kind: "directive", type: ChipKeyboardNavigationDirective, selector: "[kendoChipKeyboardNavigation]", outputs: ["reorder"] }, { kind: "component", type: ChipMenuComponent, selector: "kendo-pivot-chip-menu", inputs: ["chip", "tabIndex", "isMeasureField", "anchor"] }, { kind: "component", type: ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PivotGridConfiguratorComponent, decorators: [{
type: Component,
args: [{
selector: 'kendo-pivotgrid-configurator',
providers: [
ConfiguratorService,
DropCueService,
SinglePopupService
],
template: `
<div
class="k-pivotgrid-configurator-panel k-pivotgrid-configurator-push"
[ngClass]="{
'k-pivotgrid-configurator-horizontal': isHorizontal,
'k-pivotgrid-configurator-vertical': !isHorizontal
}"
>
<div class="k-pivotgrid-configurator-header">
<div
[id]="headerTextId"
class="k-pivotgrid-configurator-header-text">{{messageFor('configuratorHeaderText')}}</div>
</div>
<div class="k-pivotgrid-configurator-content">
<div class="k-form k-form-md" [class.k-form-horizontal]="isHorizontal" [class.k-form-vertical]="!isHorizontal" role="form">
<div class="k-form-field-wrapper" [ngStyle]="isHorizontal ? {'padding-left': 0 } : null">
<div class="k-form-field" [style]="'padding-top: 1em; margin-top: 0;'" [ngStyle]="isHorizontal ? {'padding-top': 0, 'padding-left': '16px' } : null">
<span [id]="contentLabelId('fields')" class="k-label">{{messageFor('configuratorFieldsText')}}</span>
</div>
<div class="k-form-field" [style]="'padding-top: 1em; margin-top: 0;'" [ngStyle]="isHorizontal ? {'padding-top': 0, 'padding-left': '16px' } : null">
<div class="k-fields-list-wrapper">
<kendo-treeview
#treeview
[attr.aria-labelledby]="headerTextId + ' ' + contentLabelId('fields')"
(focus)="treeview.focus()"
[nodes]="fields"
textField="caption"
[children]="children"
[hasChildren]="hasChildren"
kendoTreeViewCheckable
[hasCheckbox]="isSelectable"
[(checkedKeys)]="checked"
[checkBy]="checkItemBy"
(checkedChange)="handleCheckedChange($event)"
kendoTreeViewExpandable
(childrenLoaded)="handleChildrenLoaded($event)"
(keydown.space)="onTreeViewSelect($event)">
</kendo-treeview>
</div>
</div>
</div>
<div *ngIf="isHorizontal; else verticalTemplate" class="k-form-field-wrapper" [ngStyle]="isHorizontal ? {'padding-left': 0 } : null">
<ng-container *ngTemplateOutlet="verticalTemplate"></ng-container>
</div>
<ng-template #verticalTemplate>
<div class="k-form-field" kendoDropTarget axes="columnAxes" [style]="'padding-top: 1em; margin-top: 0;'" [ngStyle]="isHorizontal ? {'padding-top': 0, 'padding-left': '16px' } : null">
<span [id]="contentLabelId('columns')" class="k-label">{{messageFor('configuratorColumnsText')}}</span>
</div>
<kendo-chiplist
*ngIf="state.columnAxes && state.columnAxes.length; else noColumnAxes"
[navigable]="false"
#columnsChiplist
kendoDropTarget
class="k-column-fields"
axes="columnAxes"
[style.width.%]="100"
[attr.aria-labelledby]="headerTextId + ' ' + contentLabelId('columns')"
[ngStyle]="isHorizontal ? {'padding-top': 0, 'padding-left': '16px' } : null"
>
<ng-container *ngFor="let item of state.columnAxes">
<kendo-chip *ngIf="item.name.length === 1"
#chip
kendoChipDraggable
kendoDraggable
kendoDropTarget
kendoChipKeyboardNavigation
[item]="item"
[label]="getName(item.name)"
axes="columnAxes"
[removable]="true"
[hasMenu]="true"
(menuToggle)="chipMenuColumns.toggle($event)"
(remove)="onChipRemove($event, item, 'column')"
(reorder)="onReorder($event, 'column', item)"
>
<kendo-pivot-chip-menu
#chipMenuColumns
[chip]="item"
[anchor]="chip"
></kendo-pivot-chip-menu>
</kendo-chip>
</ng-container>
</kendo-chiplist>
<ng-template #noColumnAxes>
<div class="k-settings-description" kendoDropTarget axes="columnAxes">{{messageFor('configuratorEmptyColumnsText')}}</div>
</ng-template>
<div class="k-form-field" kendoDropTarget axes="rowAxes" [style]="'padding-top: 1em; margin-top: 0;'" [ngStyle]="isHorizontal ? {'padding-top': 0, 'padding-left': '16px' } : null">
<span [id]="contentLabelId('rows')" class="k-label">{{messageFor('configuratorRowsText')}}</span>
</div>
<kendo-chiplist
*ngIf="state.rowAxes && state.rowAxes.length; else noRowAxes"
[navigable]="false"
#rowsChiplist
kendoDropTarget
class="k-row-fields"
axes="rowAxes"
[attr.aria-labelledby]="headerTextId + ' ' + contentLabelId('rows')"
[ngStyle]="isHorizontal ? {'padding-top': 0, 'padding-left': '16px' } : null"
[style.width.%]="100"
>
<ng-container *ngFor="let item of state.rowAxes">
<kendo-chip *ngIf="item.name.length === 1"
#chip
kendoChipDraggable
kendoDraggable
kendoDropTarget
kendoChipKeyboardNavigation
[item]="item"
[label]="getName(item.name)"
axes="rowAxes"
[removable]="true"
[hasMenu]="true"
(menuToggle)="chipMenuRows.toggle($event)"
(remove)="onChipRemove($event, item, 'row')"
(reorder)="onReorder($event, 'row', item)"
>
<kendo-pivot-chip-menu
#chipMenuRows
[chip]="item"
[anchor]="chip"
></kendo-pivot-chip-menu>
</kendo-chip>
</ng-container>
</kendo-chiplist>
<ng-template #noRowAxes>
<div class="k-settings-description" kendoDropTarget axes="rowAxes">{{messageFor('configuratorEmptyRowsText')}}</div>
</ng-template>
</ng-template>
<div *ngIf="isHorizontal; else verticalMeasuresTemplate" class="k-form-field-wrapper" [ngStyle]="isHorizontal ? {'padding-left': 0 } : null" >
<ng-container *ngTemplateOutlet="verticalMeasuresTemplate"></ng-container>
</div>
<ng-template #verticalMeasuresTemplate>
<div class="k-form-field" kendoDropTarget axes="measureAxes" [style]="'padding-top: 1em; margin-top: 0;'" [ngStyle]="isHorizontal ? {'padding-top': 0, 'padding-left': '16px' } : null">
<span [id]="contentLabelId('values')" class="k-label">{{messageFor('configuratorValuesText')}}</span>
</div>
<kendo-chiplist
*ngIf="state.measureAxes && state.measureAxes.length; else noMeasureAxes"
[navigable]="false"
kendoDropTarget
class="k-filter-fields"
axes="measureAxes"
[attr.aria-labelledby]="headerTextId + ' ' + contentLabelId('values')"
[ngStyle]="isHorizontal ? {'padding-top': 0, 'padding-left': '16px' } : null"
[style.width.%]="100"
>
<kendo-chip *ngFor="let item of state.measureAxes"
#chip
kendoChipDraggable
kendoDraggable
kendoDropTarget
kendoChipKeyboardNavigation
[item]="item"
[label]="getName(item.name)"
axes="measureAxes"
[removable]="true"
[hasMenu]="true"
(menuToggle)="chipMenuValues.toggle($event)"
(remove)="onChipRemove($event, item, 'measure')"
(reorder)="onReorder($event, 'measure', item)"
>
<kendo-pivot-chip-menu
#chipMenuValues
[chip]="item"
[anchor]="chip"
></kendo-pivot-chip-menu>
</kendo-chip>
</kendo-chiplist>
<ng-template #noMeasureAxes>
<div class="k-settings-description" kendoDropTarget axes="measureAxes">{{messageFor('configuratorEmptyMeasuresText')}}</div>
</ng-template>
</ng-template>
</div>
</div>
<div class="k-pivotgrid-configurator-actions k-actions k-actions-end k-actions-horizontal">
<button kendoButton type="button" (click)="handleReset()">{{messageFor('configuratorCancelButtonText')}}</button>
<button kendoButton themeColor="primary" type="button" (click)="handleSubmit()">{{messageFor('configuratorApplyButtonText')}}</button>
</div>
</div>
`,
standalone: true,
imports: [
NgClass, NgStyle, TreeViewComponent, ExpandDirective, CheckDirective, NgIf,
NgTemplateOutlet, DropTargetDirective, ChipListComponent, NgFor, ChipComponent, DraggableChipDirective,
DraggableDirective, ChipKeyboardNavigationDirective, ChipMenuComponent, ButtonComponent
]
}]
}], ctorParameters: function () { return [{ type: i1.PivotGridDataService }, { type: i2.LocalizationService }, { type: i3.ConfiguratorService }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }]; }, propDecorators: { hostClass: [{
type: HostBinding,
args: ['class.k-pivotgrid-configurator']
}], hostAriaRole: [{
type: HostBinding,
args: ['attr.role']
}], headerTextId: [{
type: HostBinding,
args: ['attr.aria-labelledby']
}], orientation: [{
type: Input
}], sort: [{
type: Input
}], filter: [{
type: Input
}], navigation: [{
type: Input
}], close: [{
type: Output
}], treeView: [{
type: ViewChild,
args: [TreeViewComponent]
}], columnsList: [{
type: ViewChild,
args: ['columnsChiplist']
}], rowsList: [{
type: ViewChild,
args: ['rowsChiplist']
}] } });