Skip to content

Commit a2defd7

Browse files
MKirovaMKirova
authored andcommitted
chore(*): Refactor the row dimensions in a different container and use MRL to render cells that span multiple rows to merge common groups for row dims.
1 parent e21f61b commit a2defd7

11 files changed

+287
-131
lines changed

projects/igniteui-angular/src/lib/grids/columns/column.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1789,7 +1789,7 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy, ColumnTy
17891789
*/
17901790
public getGridTemplate(isRow: boolean): string {
17911791
if (isRow) {
1792-
const rowsCount = this.grid.multiRowLayoutRowSize;
1792+
const rowsCount = !this.grid.isPivot ? this.grid.multiRowLayoutRowSize : this.children.length - 1;
17931793
return `repeat(${rowsCount},1fr)`;
17941794
} else {
17951795
return this.getColumnSizesString(this.children);

projects/igniteui-angular/src/lib/grids/headers/grid-header-group.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<ng-container *ngIf="grid.hasColumnLayouts && column.columnGroup">
1+
<ng-container *ngIf="(grid.hasColumnLayouts || grid.isPivot) && column.columnLayout">
22
<span *ngIf="grid.hasMovableColumns" class="igx-grid-th__drop-indicator-left"></span>
33
<div class="igx-grid-thead__group igx-grid__mrl-block"
44
[ngClass]="{
@@ -32,7 +32,7 @@
3232
{{column.expanded ? 'expand_more' : 'chevron_right'}} </igx-icon>
3333
</ng-template>
3434

35-
<ng-container *ngIf="!grid.hasColumnLayouts && column.columnGroup">
35+
<ng-container *ngIf="!grid.hasColumnLayouts && column.columnGroup && !column.columnLayout">
3636
<span *ngIf="grid.hasMovableColumns" class="igx-grid-th__drop-indicator-left"></span>
3737
<div class="igx-grid-thead__title"
3838
role="columnheader"

projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.component.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,19 @@
1919
</igx-pivot-header-row>
2020

2121
<div igxGridBody (keydown.control.c)="copyHandler($event)" (copy)="copyHandler($event)" class="igx-grid__tbody" role="rowgroup">
22+
<div #rowDimensionContainer role="rowgroup" class='igx-grid__tbody-pivot-dimension'>
23+
<ng-template igxGridFor let-rowData [igxGridForOf]="dataView
24+
| pivotGridMRL:pivotConfiguration:pivotKeys:pipeTrigger"
25+
let-rowIndex="index" [igxForScrollOrientation]="'vertical'" [igxForScrollContainer]='verticalScroll'
26+
[igxForContainerSize]='calcHeight'
27+
[igxForItemSize]="hasColumnLayouts ? rowHeight * multiRowLayoutRowSize + 1 : renderedRowHeight"
28+
#verticalRowDimScrollContainer>
29+
<igx-pivot-row-dimension-content role='row' class="igx-grid-thead" [grid]="this" [hasMRL]="hasColumnLayouts"
30+
[rowIndex]='rowIndex' [rowData]='rowData'
31+
[density]="displayDensity" [activeDescendant]="activeDescendant" [width]="pivotRowWidths">
32+
</igx-pivot-row-dimension-content>
33+
</ng-template>
34+
</div>
2235
<div class="igx-grid__tbody-content" tabindex="0" [attr.role]="dataView.length ? null : 'row'" (keydown)="navigation.handleNavigation($event)" (focus)="navigation.focusTbody($event)"
2336
(dragStop)="selectionService.dragMode = $event" (scroll)='preventContainerScroll($event)'
2437
(dragScroll)="dragScroll($event)" [igxGridDragSelect]="selectionService.dragMode"

projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.interface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,5 @@ export interface IPivotDimensionData {
117117
column: ColumnType;
118118
dimension: IPivotDimension;
119119
prevDimensions: IPivotDimension[];
120+
isChild?: boolean;
120121
}

projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.module.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { IgxGridModule } from '../grid/grid.module';
33
import { IgxPivotGridComponent } from './pivot-grid.component';
44
import { IgxPivotRowComponent } from './pivot-row.component';
55
import { IgxPivotRowPipe, IgxPivotColumnPipe, IgxPivotGridFilterPipe,
6-
IgxPivotRowExpansionPipe, IgxPivotGridSortingPipe, IgxPivotGridColumnSortingPipe } from './pivot-grid.pipes';
6+
IgxPivotRowExpansionPipe, IgxPivotGridSortingPipe, IgxPivotGridColumnSortingPipe, IgxPivotRowMRLPipe } from './pivot-grid.pipes';
77
import { IgxGridComponent } from '../grid/grid.component';
88
import { IgxPivotHeaderRowComponent } from './pivot-header-row.component';
99
import { IgxPivotRowDimensionContentComponent } from './pivot-row-dimension-content.component';
@@ -24,7 +24,8 @@ import { IgxPivotRowDimensionHeaderGroupComponent } from './pivot-row-dimension-
2424
IgxPivotColumnPipe,
2525
IgxPivotGridFilterPipe,
2626
IgxPivotGridSortingPipe,
27-
IgxPivotGridColumnSortingPipe
27+
IgxPivotGridColumnSortingPipe,
28+
IgxPivotRowMRLPipe
2829
],
2930
exports: [
3031
IgxGridModule,
@@ -38,7 +39,8 @@ import { IgxPivotRowDimensionHeaderGroupComponent } from './pivot-row-dimension-
3839
IgxPivotColumnPipe,
3940
IgxPivotGridFilterPipe,
4041
IgxPivotGridSortingPipe,
41-
IgxPivotGridColumnSortingPipe
42+
IgxPivotGridColumnSortingPipe,
43+
IgxPivotRowMRLPipe
4244
],
4345
imports: [
4446
IgxGridModule,

projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.pipes.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { cloneArray } from '../../core/utils';
33
import { DataUtil } from '../../data-operations/data-util';
44
import { FilteringExpressionsTree, IFilteringExpressionsTree } from '../../data-operations/filtering-expressions-tree';
55
import { IFilteringStrategy } from '../../data-operations/filtering-strategy';
6-
import { DEFAULT_PIVOT_KEYS, IPivotConfiguration, IPivotKeys } from './pivot-grid.interface';
6+
import { DEFAULT_PIVOT_KEYS, IPivotConfiguration, IPivotDimension, IPivotKeys, PivotDimensionType } from './pivot-grid.interface';
77
import {
88
DefaultPivotSortingStrategy, DimensionValuesFilteringStrategy, PivotColumnDimensionsStrategy,
99
PivotRowDimensionsStrategy
@@ -15,6 +15,8 @@ import { GridType, IGX_GRID_BASE } from '../common/grid.interface';
1515
import { GridBaseAPIService } from '../api.service';
1616
import { IgxGridBaseDirective } from '../grid-base.directive';
1717
import { IGridSortingStrategy } from '../common/strategy';
18+
import { IGroupByResult } from '../../data-operations/grouping-result.interface';
19+
import { IGroupingExpression } from '../../data-operations/grouping-expression.interface';
1820

1921
/**
2022
* @hidden
@@ -96,6 +98,43 @@ export class IgxPivotRowExpansionPipe implements PipeTransform {
9698
}
9799
}
98100

101+
/**
102+
* @hidden
103+
*/
104+
@Pipe({
105+
name: 'pivotGridMRL',
106+
pure: true
107+
})
108+
export class IgxPivotRowMRLPipe implements PipeTransform {
109+
constructor(@Inject(IGX_GRID_BASE) private grid: GridType) { }
110+
public transform(
111+
collection: any[],
112+
config: IPivotConfiguration,
113+
pivotKeys: IPivotKeys,
114+
_pipeTrigger?: number
115+
): any[] {
116+
if (collection.length === 0 || config.rows.length === 0) return collection;
117+
let data = [];
118+
let groupData = [];
119+
let prev;
120+
const dim = config.rows[0];
121+
for (let rec of collection) {
122+
const dimData = PivotUtil.getDimensionLevel(dim, rec, pivotKeys);
123+
const val = rec[dimData.dimension.memberName];
124+
if (prev !== val && groupData.length > 0) {
125+
groupData[0][dim.memberName + pivotKeys.rowDimensionSeparator + pivotKeys.children] = groupData;
126+
if (data.indexOf(groupData[0]) === -1) {
127+
data.push(groupData[0]);
128+
}
129+
groupData = [];
130+
}
131+
groupData.push(rec);
132+
prev = val;
133+
}
134+
return data;
135+
}
136+
}
137+
99138

100139
/**
101140
* @hidden
Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,33 @@
11
<div role="rowgroup" class="igx-grid-thead__wrapper" [style.width.px]="width"
22
[attr.aria-activedescendant]="activeDescendant" [class.igx-grid__tr--mrl]="hasMRL">
3-
<!-- Column headers area -->
43
<div class="igx-grid__tr" role="row" [style.width.px]="width">
5-
<!-- Unpinned columns collection -->
64
<ng-template ngFor #headerVirtualContainer let-column
7-
[ngForOf]="unpinnedColumnCollection | igxTopLevel">
5+
[ngForOf]="rowDimension">
86
<igx-pivot-row-dimension-header-group [ngClass]="column.headerGroupClasses"
97
[ngStyle]="column.headerGroupStyles |igxHeaderGroupStyle:column:grid.pipeTrigger" [column]="column"
108
[style.min-width]="column.calcWidth | igxHeaderGroupWidth:grid.defaultHeaderGroupMinWidth:hasMRL"
119
[style.flex-basis]="column.calcWidth | igxHeaderGroupWidth:grid.defaultHeaderGroupMinWidth:hasMRL"
12-
[intRow]="intRow">
10+
[rowIndex]="rowIndex">
1311
</igx-pivot-row-dimension-header-group>
1412
</ng-template>
1513
</div>
16-
</div>
14+
</div>
15+
16+
<ng-template #headerTemplate let-column>
17+
<div class='igx-grid__tr--header igx-grid__row-indentation--level-{{getLevel(column)}}'
18+
(click)="this.selectPivotRow(column, $event)">
19+
<igx-icon [attr.draggable]=" false" (click)="grid.toggleRow(getRowDimensionKey(column))">
20+
{{ getExpandState(column) ? 'expand_more' : 'chevron_right'}}</igx-icon>
21+
{{column.header}}
22+
</div>
23+
</ng-template>
24+
25+
<ng-template #headerDefaultTemplate let-column>
26+
27+
<div class='igx-grid__tr--header igx-grid__row-indentation--level-{{getLevel(column)}}'
28+
(click)="this.selectPivotRow(column, $event)">
29+
<igx-icon style='flex-shrink: 0;' [attr.draggable]=" false">
30+
</igx-icon>
31+
{{column.header}}
32+
</div>
33+
</ng-template>

projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-content.component.ts

Lines changed: 197 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,24 @@
11
import {
22
ChangeDetectionStrategy,
3+
ChangeDetectorRef,
34
Component,
4-
Input
5+
ComponentFactoryResolver,
6+
ElementRef,
7+
Inject,
8+
Input,
9+
SimpleChanges,
10+
TemplateRef,
11+
ViewChild,
12+
ViewContainerRef
513
} from '@angular/core';
14+
import { IgxColumnGroupComponent } from '../columns/column-group.component';
15+
import { IgxColumnLayoutComponent } from '../columns/column-layout.component';
16+
import { IgxColumnComponent } from '../columns/column.component';
17+
import { IGX_GRID_BASE, PivotGridType } from '../common/grid.interface';
618
import { IgxGridHeaderRowComponent } from '../headers/grid-header-row.component';
719
import { IgxRowDirective } from '../row.directive';
20+
import { IPivotDimension, IPivotDimensionData } from './pivot-grid.interface';
21+
import { PivotUtil } from './pivot-util';
822

923
/**
1024
*
@@ -25,5 +39,186 @@ export class IgxPivotRowDimensionContentComponent extends IgxGridHeaderRowCompon
2539
* @internal
2640
*/
2741
@Input()
28-
public intRow: IgxRowDirective;
42+
public rowIndex: number;
43+
44+
@Input()
45+
public rowData: any;
46+
47+
/**
48+
* @hidden @internal
49+
*/
50+
@ViewChild('headerTemplate', { read: TemplateRef, static: true })
51+
public headerTemplate: TemplateRef<any>;
52+
53+
/**
54+
* @hidden @internal
55+
*/
56+
@ViewChild('headerDefaultTemplate', { read: TemplateRef, static: true })
57+
public headerTemplateDefault: TemplateRef<any>;
58+
59+
constructor(
60+
@Inject(IGX_GRID_BASE) public grid: PivotGridType,
61+
protected ref: ElementRef<HTMLElement>,
62+
protected cdr: ChangeDetectorRef,
63+
protected resolver: ComponentFactoryResolver,
64+
protected viewRef: ViewContainerRef
65+
) {
66+
super(ref, cdr);
67+
}
68+
protected rowDimensionData: IPivotDimensionData[] = [];
69+
70+
public get rowDimension() {
71+
return this.rowDimensionData?.filter(x => !x.isChild).map(x => x.column);
72+
}
73+
74+
/**
75+
* @hidden
76+
* @internal
77+
*/
78+
public ngOnChanges(changes: SimpleChanges) {
79+
const rowDimConfig = this.grid.rowDimensions;
80+
if (changes.data || rowDimConfig.length !== this.rowDimensionData.length) {
81+
// generate new rowDimension on row data change
82+
this.rowDimensionData = [];
83+
this.viewRef.clear();
84+
this.extractFromDimensions(rowDimConfig, 0);
85+
this.viewRef.clear();
86+
}
87+
if (changes.pivotRowWidths && this.rowDimensionData) {
88+
for (const dim of rowDimConfig) {
89+
const dimData = PivotUtil.getDimensionLevel(dim, this.rowData, this.grid.pivotKeys);
90+
const data = this.rowDimensionData.find(x => x.dimension.memberName === dimData.dimension.memberName);
91+
data.column.width = this.grid.resolveRowDimensionWidth(dim) + 'px';
92+
}
93+
}
94+
}
95+
96+
97+
/**
98+
* @hidden
99+
* @internal
100+
*/
101+
public getRowDimensionKey(col: IgxColumnComponent) {
102+
const dimData = this.rowDimensionData.find(x => x.column.field === col.field);
103+
const key = PivotUtil.getRecordKey(this.rowData, dimData.dimension, dimData.prevDimensions, this.grid.pivotKeys);
104+
return key;
105+
}
106+
107+
public getExpandState(col: IgxColumnComponent) {
108+
return this.grid.gridAPI.get_row_expansion_state(this.getRowDimensionKey(col));
109+
}
110+
111+
public getLevel(col: IgxColumnComponent) {
112+
return this.rowData[col.field + this.grid.pivotKeys.rowDimensionSeparator + this.grid.pivotKeys.level];
113+
}
114+
115+
116+
/**
117+
* @hidden @internal
118+
*/
119+
public selectPivotRow(col: any, event?: any) {
120+
if (this.grid.rowSelection === 'none') {
121+
return;
122+
}
123+
event?.stopPropagation();
124+
const key = this.getRowDimensionKey(col);
125+
if (this.grid.selectionService.isRowSelected(key)) {
126+
this.grid.selectionService.deselectRow(key, event);
127+
} else {
128+
this.grid.selectionService.selectRowById(key, true, event);
129+
}
130+
}
131+
132+
protected extractFromDimensions(rowDimConfig: IPivotDimension[], level: number) {
133+
let dimIndex = 0;
134+
let currentLvl = 0;
135+
currentLvl += level;
136+
const prev = [];
137+
let prevDim;
138+
for (const dim of rowDimConfig) {
139+
const dimData = PivotUtil.getDimensionLevel(dim, this.rowData, this.grid.pivotKeys);
140+
dimIndex += dimData.level;
141+
currentLvl += dimData.level;
142+
const prevChildren = prevDim ? this.rowData[prevDim.memberName + this.grid.pivotKeys.rowDimensionSeparator + this.grid.pivotKeys.children] : [];
143+
if (prevChildren && prevChildren.length > 0) {
144+
const childrenCols = [];
145+
const layoutCol = this.rowDimensionData.find(x => x.column.columnLayout).column;
146+
prevChildren.forEach((childData, index) => {
147+
const dimData = PivotUtil.getDimensionLevel(dim, childData, this.grid.pivotKeys);
148+
dimIndex += dimData.level;
149+
currentLvl += dimData.level;
150+
const column = this.extractFromDimension(dimData.dimension, childData, [], dimIndex, currentLvl, dim, [...prev]);
151+
column.rowStart = index + 1;
152+
column.rowEnd = index + 2;
153+
column.colStart = 2;
154+
childrenCols.push(column);
155+
this.rowDimensionData.push({
156+
column,
157+
dimension: dimData.dimension,
158+
prevDimensions: [...prev],
159+
isChild: true
160+
});
161+
});
162+
const all_children = layoutCol.children.toArray().concat(childrenCols);
163+
layoutCol.children.reset(all_children);
164+
continue;
165+
}
166+
const children = this.rowData[dim.memberName + this.grid.pivotKeys.rowDimensionSeparator + this.grid.pivotKeys.children];
167+
const column = this.extractFromDimension(dimData.dimension, this.rowData, children, dimIndex, currentLvl, dim, [...prev]);
168+
this.rowDimensionData.push({
169+
column,
170+
dimension: dimData.dimension,
171+
prevDimensions: [...prev]
172+
});
173+
prevDim = dim;
174+
prev.push(dimData.dimension);
175+
}
176+
}
177+
178+
protected extractFromDimension(dim: IPivotDimension, rowData: any[], children: any[], index: number = 0, lvl = 0, rootDim: IPivotDimension, prevDims) {
179+
const field = dim.memberName;
180+
const header = rowData[field];
181+
let col;
182+
if (children && children.length > 0) {
183+
const ref = this.viewRef.createComponent(IgxColumnLayoutComponent);
184+
col = ref.instance;
185+
ref.instance.field = 'group';
186+
const childCol = this._createColComponent(field, header, children, index, dim, lvl, rootDim);
187+
ref.instance.children.reset([childCol]);
188+
this.rowDimensionData.push({
189+
column: childCol,
190+
dimension: dim,
191+
prevDimensions: prevDims,
192+
isChild: true
193+
});
194+
} else {
195+
col = this._createColComponent(field, header, children, index, dim, lvl, rootDim);
196+
}
197+
return col;
198+
}
199+
200+
protected _createColComponent(field: string, header: string, children: any[],
201+
index: number = 0,
202+
dim: IPivotDimension, lvl = 0, rootDim: IPivotDimension) {
203+
const ref = this.viewRef.createComponent(IgxColumnComponent);
204+
if (children && children.length > 0) {
205+
ref.instance.rowStart = 1;
206+
ref.instance.rowEnd = children.length + 1;
207+
ref.instance.colStart = 1;
208+
} else {
209+
ref.instance.colStart = 2;
210+
ref.instance.rowStart = 1;
211+
ref.instance.rowEnd = 2;
212+
}
213+
ref.instance.field = field;
214+
ref.instance.header = header;
215+
ref.instance.width = this.grid.resolveRowDimensionWidth(rootDim) + 'px';
216+
(ref as any).instance._vIndex = this.grid.columns.length + index + this.rowIndex * this.grid.pivotConfiguration.rows.length;
217+
if (dim.childLevel && lvl >= PivotUtil.getTotalLvl(this.rowData, this.grid.pivotKeys)) {
218+
ref.instance.headerTemplate = this.headerTemplate;
219+
} else {
220+
ref.instance.headerTemplate = this.headerTemplateDefault;
221+
}
222+
return ref.instance;
223+
}
29224
}

0 commit comments

Comments
 (0)