Skip to content

Commit 41e761d

Browse files
committed
Merge branch 'pivot-grid-master' into skrastev/fix-10639
2 parents 37f6c76 + 36293dd commit 41e761d

File tree

12 files changed

+448
-139
lines changed

12 files changed

+448
-139
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@ export interface PivotGridType extends GridType {
628628
setupColumns(): void;
629629
toggleRow(rowID: any): void;
630630
resolveDataTypes(field: any): GridColumnDataType;
631+
resolveRowDimensionWidth(dim: IPivotDimension): number;
631632
dimensionsChange: EventEmitter<IDimensionsChange>;
632633
valuesChange: EventEmitter<IValuesChange>;
633634
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@
4747
</ng-template>
4848
</ng-template>
4949
<ng-template #record_template let-rowIndex="index" let-rowData>
50-
<igx-pivot-row [gridID]="id" [index]="rowIndex" [data]="rowData" [ngClass]="rowClasses | igxGridRowClasses:row:row.inEditMode:row.selected:row.dirty:row.deleted:row.dragging:rowIndex:hasColumnLayouts:false:pipeTrigger"
50+
<igx-pivot-row [pivotRowWidths]='pivotRowWidths' [gridID]="id" [index]="rowIndex" [data]="rowData"
51+
[ngClass]="rowClasses | igxGridRowClasses:row:row.inEditMode:row.selected:row.dirty:row.deleted:row.dragging:rowIndex:hasColumnLayouts:false:pipeTrigger"
5152
[ngStyle]="rowStyles | igxGridRowStyles:rowData:rowIndex:pipeTrigger" #row>
5253
</igx-pivot-row>
5354
</ng-template>

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

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ import { DataUtil } from '../../data-operations/data-util';
6161
import { IFilteringExpressionsTree } from '../../data-operations/filtering-expressions-tree';
6262
import { IgxGridTransaction } from '../common/types';
6363
import { SortingDirection } from '../../data-operations/sorting-strategy';
64-
import { IgxGridAPIService } from '../grid/grid-api.service';
6564
import { GridBaseAPIService } from '../api.service';
6665

6766
let NEXT_ID = 0;
@@ -445,6 +444,35 @@ export class IgxPivotGridComponent extends IgxGridBaseDirective implements OnIni
445444
public set batchEditing(_val: boolean) {
446445
}
447446

447+
public get selectedRows(): any[] {
448+
if (!this.selectionService.getSelectedRows()) {
449+
return [];
450+
}
451+
const selectedRowIds = [];
452+
this.dataView.forEach(record => {
453+
const prev = [];
454+
for (const dim of this.rowDimensions) {
455+
let currDim = dim;
456+
let shouldBreak = false;
457+
do {
458+
const key = PivotUtil.getRecordKey(record, currDim, prev);
459+
if (this.selectionService.isPivotRowSelected(key) && !selectedRowIds.find(x => x === record)) {
460+
selectedRowIds.push(record);
461+
shouldBreak = true;
462+
break;
463+
}
464+
currDim = currDim.childLevel;
465+
} while (currDim);
466+
prev.push(dim);
467+
if (shouldBreak) {
468+
break;
469+
}
470+
}
471+
472+
});
473+
474+
return selectedRowIds;
475+
}
448476

449477
constructor(
450478
public selectionService: IgxGridSelectionService,
@@ -661,8 +689,19 @@ export class IgxPivotGridComponent extends IgxGridBaseDirective implements OnIni
661689
}
662690

663691
public get pivotRowWidths() {
664-
const rowDimCount = this.rowDimensions.length;
665-
return MINIMUM_COLUMN_WIDTH * rowDimCount || MINIMUM_COLUMN_WIDTH;
692+
return this.rowDimensions.reduce((accumulator, dim) => accumulator + this.resolveRowDimensionWidth(dim), 0);
693+
}
694+
695+
public resolveRowDimensionWidth(dim: IPivotDimension): number {
696+
if(!dim.width) {
697+
return MINIMUM_COLUMN_WIDTH;
698+
}
699+
const isPercent = dim.width && dim.width.indexOf('%') !== -1;
700+
if (isPercent) {
701+
return parseFloat(dim.width) / 100 * this.calcWidth;
702+
} else {
703+
return parseInt(dim.width, 10);
704+
}
666705
}
667706

668707
public get rowDimensions() {
@@ -1063,13 +1102,14 @@ export class IgxPivotGridComponent extends IgxGridBaseDirective implements OnIni
10631102
ref.instance.header = parent != null ? key.split(parent.header + '-')[1] : key;
10641103
ref.instance.field = key;
10651104
ref.instance.parent = parent;
1105+
ref.instance.width = value.dimension.width || MINIMUM_COLUMN_WIDTH + 'px';
10661106
ref.instance.dataType = this.pivotConfiguration.values[0]?.dataType || this.resolveDataTypes(data[0][key]);
10671107
ref.instance.formatter = this.pivotConfiguration.values[0]?.formatter;
10681108
ref.instance.sortable = true;
10691109
ref.changeDetectorRef.detectChanges();
10701110
columns.push(ref.instance);
10711111
if (this.hasMultipleValues) {
1072-
const measureChildren = this.getMeasureChildren(factoryColumn, data, ref.instance, false);
1112+
const measureChildren = this.getMeasureChildren(factoryColumn, data, ref.instance, false, value.dimension.width);
10731113
ref.instance.children.reset(measureChildren);
10741114
columns = columns.concat(measureChildren);
10751115
}
@@ -1088,6 +1128,7 @@ export class IgxPivotGridComponent extends IgxGridBaseDirective implements OnIni
10881128
refSibling.instance.header = parent != null ? key.split(parent.header + '-')[1] : key;
10891129
refSibling.instance.field = key;
10901130
refSibling.instance.parent = parent;
1131+
ref.instance.width = value.dimension.width || MINIMUM_COLUMN_WIDTH + 'px';
10911132
ref.instance.sortable = true;
10921133
refSibling.instance.hidden = true;
10931134
refSibling.instance.dataType = this.pivotConfiguration.values[0]?.dataType || this.resolveDataTypes(data[0][key]);
@@ -1099,7 +1140,7 @@ export class IgxPivotGridComponent extends IgxGridBaseDirective implements OnIni
10991140
ref.changeDetectorRef.detectChanges();
11001141
columns.push(ref.instance);
11011142
if (this.hasMultipleValues) {
1102-
const measureChildren = this.getMeasureChildren(factoryColumn, data, ref.instance, true);
1143+
const measureChildren = this.getMeasureChildren(factoryColumn, data, ref.instance, true, value.dimension.width);
11031144
const nestedChildren = filteredChildren.concat(measureChildren);
11041145
const allChildren = children.concat(measureChildren);
11051146
ref.instance.children.reset(nestedChildren);
@@ -1114,13 +1155,17 @@ export class IgxPivotGridComponent extends IgxGridBaseDirective implements OnIni
11141155
return columns;
11151156
}
11161157

1117-
protected getMeasureChildren(colFactory, data, parent, hidden) {
1158+
protected getMeasureChildren(colFactory, data, parent, hidden, parentWidth) {
11181159
const cols = [];
1160+
const count = this.values.length;
1161+
const width = parentWidth ? parseInt(parentWidth, 10) / count : MINIMUM_COLUMN_WIDTH;
1162+
const isPercent = parentWidth && parentWidth.indexOf('%') !== -1;
11191163
this.values.forEach(val => {
11201164
const ref = colFactory.create(this.viewRef.injector);
11211165
ref.instance.header = val.displayName || val.member;
11221166
ref.instance.field = parent.field + '-' + val.member;
11231167
ref.instance.parent = parent;
1168+
ref.instance.width = isPercent ? width + '%' : width + 'px';
11241169
ref.instance.hidden = hidden;
11251170
ref.instance.sortable = true;
11261171
ref.instance.dataType = val.dataType || this.resolveDataTypes(data[0][val.member]);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ export interface IPivotDimension {
6666
filter?: FilteringExpressionsTree | null;
6767
sortDirection?: SortingDirection;
6868
dataType?: GridColumnDataType;
69+
// The width of the dimension cells to be rendered.Can be pixel or %.
70+
width? : string;
6971
}
7072

7173
export interface IPivotValue {

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

Lines changed: 134 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import { By } from '@angular/platform-browser';
33
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
44
import { IgxPivotGridModule } from 'igniteui-angular';
55
import { configureTestSuite } from '../../test-utils/configure-suite';
6-
import { GridFunctions } from '../../test-utils/grid-functions.spec';
7-
import { IgxPivotGridTestBaseComponent, IgxTotalSaleAggregate } from '../../test-utils/pivot-grid-samples.spec';
6+
import { GridFunctions, GridSelectionFunctions } from '../../test-utils/grid-functions.spec';
7+
import { IgxPivotGridTestBaseComponent, IgxPivotGridTestComplexHierarchyComponent, IgxTotalSaleAggregate } from '../../test-utils/pivot-grid-samples.spec';
88
import { UIInteractions } from '../../test-utils/ui-interactions.spec';
99
const CSS_CLASS_DROP_DOWN_BASE = 'igx-drop-down';
1010
const CSS_CLASS_LIST = 'igx-drop-down__list';
@@ -28,8 +28,10 @@ describe('Basic IgxPivotGrid #pivotGrid', () => {
2828
}));
2929

3030
it('should apply formatter and dataType from measures', () => {
31-
fixture.detectChanges();
3231
const pivotGrid = fixture.componentInstance.pivotGrid;
32+
pivotGrid.width = '1500px';
33+
fixture.detectChanges();
34+
3335
const actualFormatterValue = pivotGrid.rowList.first.cells.first.title;
3436
expect(actualFormatterValue).toEqual('774$');
3537
const actualDataTypeValue = pivotGrid.rowList.first.cells.last.title;
@@ -330,8 +332,9 @@ describe('Basic IgxPivotGrid #pivotGrid', () => {
330332
});
331333

332334
it('should allow changing default aggregation via value chip drop-down.', () => {
333-
fixture.detectChanges();
334335
const pivotGrid = fixture.componentInstance.pivotGrid;
336+
pivotGrid.width = '1500px';
337+
fixture.detectChanges();
335338
const headerRow = fixture.nativeElement.querySelector('igx-pivot-header-row');
336339
const valueChip = headerRow.querySelector('igx-chip[id="UnitsSold"]');
337340
let content = valueChip.querySelector('.igx-chip__content');
@@ -406,3 +409,130 @@ describe('Basic IgxPivotGrid #pivotGrid', () => {
406409
});
407410
});
408411
});
412+
413+
describe('IgxPivotGrid complex hierarchy #pivotGrid', () => {
414+
let fixture;
415+
configureTestSuite((() => {
416+
TestBed.configureTestingModule({
417+
declarations: [
418+
IgxPivotGridTestComplexHierarchyComponent
419+
],
420+
imports: [
421+
NoopAnimationsModule, IgxPivotGridModule]
422+
});
423+
}));
424+
425+
beforeEach(fakeAsync(() => {
426+
fixture = TestBed.createComponent(IgxPivotGridTestComplexHierarchyComponent);
427+
fixture.detectChanges();
428+
}));
429+
430+
it('should select/deselect the correct row', () => {
431+
fixture.detectChanges();
432+
const pivotGrid = fixture.componentInstance.pivotGrid;
433+
const pivotRows = GridFunctions.getPivotRows(fixture);
434+
const row = pivotRows[2].componentInstance;
435+
row.selectPivotRow(row.rowDimensionData[1].column);
436+
fixture.detectChanges();
437+
expect(row.selected).toBeTrue();
438+
expect(pivotGrid.selectedRows).not.toBeNull();
439+
expect(pivotGrid.selectedRows.length).toBe(1);
440+
const expected =
441+
{
442+
'All cities': 'All Cities', 'All cities_level': 0,
443+
ProductCategory: 'Clothing', ProductCategory_level: 1,
444+
'Bulgaria-AmountOfSale': 3612.42, 'Bulgaria-UnitsSold': 282,
445+
'US-AmountOfSale': 14672.72, 'US-UnitsSold': 296,
446+
'Uruguay-AmountOfSale': 31158.48, 'Uruguay-UnitsSold': 456
447+
};
448+
expect(pivotGrid.selectedRows[0]).toEqual(expected);
449+
450+
//deselect
451+
row.selectPivotRow(row.rowDimensionData[1].column);
452+
fixture.detectChanges();
453+
expect(row.selected).toBeFalse();
454+
expect(pivotGrid.selectedRows.length).toBe(0);
455+
});
456+
457+
it('should select/deselect the correct group of rows', () => {
458+
fixture.detectChanges();
459+
const pivotGrid = fixture.componentInstance.pivotGrid;
460+
const pivotRows = GridFunctions.getPivotRows(fixture);
461+
const row = pivotRows[2].componentInstance;
462+
row.selectPivotRow(row.rowDimensionData[0].column);
463+
fixture.detectChanges();
464+
for (let i = 0; i < 5; ++i) {
465+
expect(pivotRows[i].componentInstance.selected).toBeTrue();
466+
}
467+
expect(pivotGrid.selectedRows).not.toBeNull();
468+
expect(pivotGrid.selectedRows.length).toBe(5);
469+
const expected =
470+
[
471+
{
472+
AllProducts: 'AllProducts', 'All cities': 'All Cities',
473+
'All cities_level': 0, AllProducts_level: 0, 'Bulgaria-UnitsSold': 774,
474+
'Bulgaria-AmountOfSale': 11509.02, 'US-UnitsSold': 296, 'US-AmountOfSale': 14672.72,
475+
'Uruguay-UnitsSold': 524, 'Uruguay-AmountOfSale': 31400.56,
476+
'UK-UnitsSold': 293, 'UK-AmountOfSale': 25074.94,
477+
'Japan-UnitsSold': 240, 'Japan-AmountOfSale': 4351.2,
478+
}, {
479+
ProductCategory: 'Bikes', 'All cities': 'All Cities',
480+
ProductCategory_level: 1, 'All cities_level': 0,
481+
'Uruguay-UnitsSold': 68, 'Uruguay-AmountOfSale': 242.08,
482+
City: 'Ciudad de la Costa', Country: 'Uruguay',
483+
Date: '01/06/2011', SellerName: 'Lydia Burson',
484+
UnitPrice: 3.56, UnitsSold: 68
485+
}, {
486+
ProductCategory: 'Clothing', 'All cities': 'All Cities',
487+
ProductCategory_level: 1, 'All cities_level': 0, 'Bulgaria-UnitsSold': 282,
488+
'Bulgaria-AmountOfSale': 3612.42, 'US-UnitsSold': 296, 'US-AmountOfSale': 14672.72,
489+
'Uruguay-UnitsSold': 456, 'Uruguay-AmountOfSale': 31158.48
490+
}, {
491+
ProductCategory: 'Accessories', 'All cities': 'All Cities',
492+
ProductCategory_level: 1, 'All cities_level': 0,
493+
'UK-UnitsSold': 293, 'UK-AmountOfSale': 25074.94,
494+
City: 'London', Country: 'UK', Date: '04/07/2012',
495+
SellerName: 'David Haley', UnitPrice: 85.58, UnitsSold: 293
496+
}, {
497+
ProductCategory: 'Components', 'All cities': 'All Cities',
498+
ProductCategory_level: 1, 'All cities_level': 0,
499+
'Japan-UnitsSold': 240, 'Japan-AmountOfSale': 4351.2,
500+
'Bulgaria-UnitsSold': 492, 'Bulgaria-AmountOfSale': 7896.6
501+
}
502+
];
503+
expect(pivotGrid.selectedRows).toEqual(expected);
504+
});
505+
506+
it('should select/deselect the correct column', () => {
507+
fixture.detectChanges();
508+
const pivotGrid = fixture.componentInstance.pivotGrid;
509+
const unitsSold = pivotGrid.getColumnByName('Bulgaria-UnitsSold');
510+
GridFunctions.clickColumnHeaderUI('Bulgaria-UnitsSold', fixture);
511+
GridSelectionFunctions.verifyColumnAndCellsSelected(unitsSold);
512+
});
513+
514+
it('should select/deselect the correct column group', () => {
515+
fixture.detectChanges();
516+
const pivotGrid = fixture.componentInstance.pivotGrid;
517+
const group = GridFunctions.getColGroup(pivotGrid, 'Bulgaria');
518+
const unitsSold = pivotGrid.getColumnByName('Bulgaria-UnitsSold');
519+
const amountOfSale = pivotGrid.getColumnByName('Bulgaria-AmountOfSale');
520+
const unitsSoldUSA = pivotGrid.getColumnByName('US-UnitsSold');
521+
const amountOfSaleUSA = pivotGrid.getColumnByName('US-AmountOfSale');
522+
523+
GridFunctions.clickColumnGroupHeaderUI('Bulgaria', fixture);
524+
fixture.detectChanges();
525+
526+
GridSelectionFunctions.verifyColumnSelected(unitsSold);
527+
GridSelectionFunctions.verifyColumnSelected(amountOfSale);
528+
GridSelectionFunctions.verifyColumnGroupSelected(fixture, group);
529+
530+
GridSelectionFunctions.verifyColumnsSelected([unitsSoldUSA, amountOfSaleUSA], false);
531+
532+
GridFunctions.clickColumnGroupHeaderUI('Bulgaria', fixture);
533+
534+
GridSelectionFunctions.verifyColumnSelected(unitsSold, false);
535+
GridSelectionFunctions.verifyColumnSelected(amountOfSale, false);
536+
GridSelectionFunctions.verifyColumnGroupSelected(fixture, group, false);
537+
});
538+
});

0 commit comments

Comments
 (0)