diff --git a/CHANGELOG.md b/CHANGELOG.md index 62f1182c6f4..dfc6c564e56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes for each version of this project will be documented in this file. +## 21.2.23 + +### Bug Fixes + +- `IgxPivotGridComponent` + - In the horizontal row layout, collapsed and summary row headers now fill all the columns they span (#17222). + ## 21.2.0 ### New Features diff --git a/projects/igniteui-angular/grids/core/src/resizing/pivot-grid/pivot-resizing.service.ts b/projects/igniteui-angular/grids/core/src/resizing/pivot-grid/pivot-resizing.service.ts index 2fbaca7072d..cde676d0eec 100644 --- a/projects/igniteui-angular/grids/core/src/resizing/pivot-grid/pivot-resizing.service.ts +++ b/projects/igniteui-angular/grids/core/src/resizing/pivot-grid/pivot-resizing.service.ts @@ -19,7 +19,10 @@ export class IgxPivotColumnResizingService extends IgxColumnResizingService { * @hidden */ public override getColumnHeaderRenderedWidth() { - return this.rowHeaderGroup.header.nativeElement.getBoundingClientRect().width; + const headerWidth = this.rowHeaderGroup.header.nativeElement.getBoundingClientRect().width; + // A collapsed or summary header spans several dimensions, but only the first one is resized. + const rowDimWidth = this.rowHeaderGroup.grid.rowDimensionWidthToPixels(this.rowHeaderGroup.parent.rootDimension); + return rowDimWidth < headerWidth ? rowDimWidth : headerWidth; } protected override _handlePixelResize(diff: number, column: ColumnType) { diff --git a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.ts b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.ts index cee54935f9a..46693d0dc55 100644 --- a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.ts +++ b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.ts @@ -2197,7 +2197,8 @@ export class IgxPivotGridComponent extends IgxGridBaseDirective implements OnIni protected autoSizeDimensionsInView() { if (!this.hasDimensionsToAutosize) return; for (const dim of this.visibleRowDimensions) { - if (dim.width === 'auto') { + // Skip sized dimensions, their merged headers span several columns. + if (dim.width === 'auto' && !dim.autoWidth) { const contentWidths = []; const relatedDims = PivotUtil.flatten([dim]).map(x => x.memberName); const contentCollection = this.getContentCollection(dim); diff --git a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.spec.ts b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.spec.ts index 9330d3472a9..202becfcc13 100644 --- a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.spec.ts +++ b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.spec.ts @@ -3157,6 +3157,123 @@ describe('IgxPivotGrid #pivotGrid', () => { expect(rowDimensionsCol4.length).toBe(0); }); + it("should size the collapsed and summary row headers to all the columns they span.", () => { + pivotGrid.pivotConfiguration.rows = [ + { + memberName: 'All cities', + memberFunction: () => 'All Cities', + enabled: true, + horizontalSummary: true, + childLevel: { + memberName: 'City', + enabled: true + } + }, { + memberFunction: () => 'AllProducts', + memberName: 'AllProducts', + enabled: true, + horizontalSummary: true, + childLevel: { + memberFunction: (data) => data.ProductCategory, + memberName: 'ProductCategory', + enabled: true, + width: '120px' + } + } + ]; + pivotGrid.pipeTrigger++; + fixture.detectChanges(); + + const getContentCells = (header: string) => fixture.debugElement + .queryAll(By.directive(IgxPivotRowDimensionContentComponent)) + .filter(x => x.componentInstance.rowDimensionColumn.header === header); + const expectHeadersToSpanTheirColumns = () => { + const contentCells = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionContentComponent)); + for (const cell of contentCells) { + const content = cell.componentInstance as IgxPivotRowDimensionContentComponent; + const spannedWidth = pivotGrid.visibleRowDimensions + .slice(content.layout.colStart - 1, content.layout.colEnd - 1) + .reduce((width, dim) => width + pivotGrid.rowDimensionWidthToPixels(dim), 0); + const header = cell.query(By.directive(IgxPivotRowDimensionHeaderComponent)).nativeElement as HTMLElement; + expect(header.getBoundingClientRect().width).withContext(content.rowDimensionColumn.header).toBe(spannedWidth); + } + }; + + // the summary headers span all columns to their right + const citiesSummary = getContentCells('All Cities Total'); + expect(citiesSummary.length).toBe(1); + expect(citiesSummary[0].componentInstance.layout.colStart).toBe(1); + expect(citiesSummary[0].componentInstance.layout.colEnd).toBe(5); + const productsSummaries = getContentCells('AllProducts Total'); + expect(productsSummaries.length).toBe(6); + productsSummaries.forEach(x => { + expect(x.componentInstance.layout.colStart).toBe(3); + expect(x.componentInstance.layout.colEnd).toBe(5); + }); + expectHeadersToSpanTheirColumns(); + + // the collapsed header spans the empty ProductCategory column + getContentCells('AllProducts')[0].query(By.directive(IgxIconComponent)).nativeElement.click(); + fixture.detectChanges(); + const collapsedProducts = getContentCells('AllProducts')[0].componentInstance.layout; + expect(collapsedProducts.colStart).toBe(3); + expect(collapsedProducts.colEnd).toBe(5); + expectHeadersToSpanTheirColumns(); + + // the same applies when the summaries are on top + pivotGrid.pivotUI = { horizontalSummariesPosition: PivotSummaryPosition.Top }; + fixture.detectChanges(); + expect(getContentCells('All Cities Total')[0].componentInstance.layout.colEnd).toBe(5); + expectHeadersToSpanTheirColumns(); + }); + + it("should not widen an auto-sized row dimension to the columns its summary headers span.", async () => { + fixture.componentInstance.pivotConfigHierarchy = { + columns: pivotGrid.pivotConfiguration.columns, + values: pivotGrid.pivotConfiguration.values, + rows: [ + { + memberName: 'All cities', + memberFunction: () => 'All Cities', + enabled: false, + width: 'auto', + childLevel: { + memberName: 'City', + enabled: true + } + }, { + memberFunction: () => 'AllProducts', + memberName: 'AllProducts', + enabled: true, + width: 'auto', + horizontalSummary: true, + childLevel: { + memberFunction: (data) => data.ProductCategory, + memberName: 'ProductCategory', + enabled: true + } + } + ] + }; + fixture.detectChanges(); + await wait(50); + fixture.detectChanges(); + + const [allCities, allProducts] = pivotGrid.pivotConfiguration.rows; + const productsWidth = allProducts.autoWidth; + expect(productsWidth).toBeGreaterThan(0); + + // Enabling another auto dimension reruns sizing. + pivotGrid.toggleDimension(allCities); + await wait(100); + fixture.detectChanges(); + await wait(50); + fixture.detectChanges(); + + expect(allCities.autoWidth).toBeGreaterThan(0); + expect(allProducts.autoWidth).toBe(productsWidth); + }); + it("should render summary rows when enabled.", () => { pivotGrid.pivotConfiguration.rows = [ { @@ -3403,6 +3520,55 @@ describe('IgxPivotGrid #pivotGrid', () => { expect(rowHeaders[0].componentInstance.column.width).toEqual('400px'); })); + it("should stop the resizer of a summary row header at the minimum width of its first dimension.", fakeAsync(() => { + pivotGrid.pivotConfiguration.rows = [ + { + memberName: 'All cities', + memberFunction: () => 'All Cities', + enabled: true, + childLevel: { + memberName: 'City', + enabled: true + } + }, { + memberFunction: () => 'AllProducts', + memberName: 'AllProducts', + enabled: true, + horizontalSummary: true, + childLevel: { + memberFunction: (data) => data.ProductCategory, + memberName: 'ProductCategory', + enabled: true, + width: '120px' + } + } + ]; + pivotGrid.pipeTrigger++; + fixture.detectChanges(); + + const summaryHeader = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderGroupComponent)) + .find(x => x.componentInstance.column.header === 'AllProducts Total'); + const allProducts = pivotGrid.pivotConfiguration.rows[1]; + const rootWidth = pivotGrid.rowDimensionWidthToPixels(allProducts); + const minWidth = summaryHeader.componentInstance.column.minWidthPx; + // the summary header spans the ProductCategory column as well, but only AllProducts is resized + expect(summaryHeader.componentInstance.header.nativeElement.getBoundingClientRect().width).toBe(rootWidth + 120); + UIInteractions.simulateMouseEvent('mousedown', GridFunctions.getHeaderResizeArea(summaryHeader).nativeElement, 500, 0); + tick(200); + fixture.detectChanges(); + tick(16); + const resizer = GridFunctions.getResizer(fixture).nativeElement; + const startLeft = parseFloat(resizer.style.left); + + UIInteractions.simulateMouseEvent('mousemove', resizer, -500, 5); + tick(16); + expect(startLeft - parseFloat(resizer.style.left)).toBe(rootWidth - minWidth); + + UIInteractions.simulateMouseEvent('mouseup', resizer, -500, 5); + fixture.detectChanges(); + expect(allProducts.width).toBe(`${minWidth}px`); + })); + it("should allow sorting each dimension column from the hierarchy.", () => { pivotGrid.pivotConfiguration.rows = [ { diff --git a/projects/igniteui-angular/grids/pivot-grid/src/pivot-row-dimension-header-group.component.ts b/projects/igniteui-angular/grids/pivot-grid/src/pivot-row-dimension-header-group.component.ts index fda18cb8240..6dac6011803 100644 --- a/projects/igniteui-angular/grids/pivot-grid/src/pivot-row-dimension-header-group.component.ts +++ b/projects/igniteui-angular/grids/pivot-grid/src/pivot-row-dimension-header-group.component.ts @@ -145,7 +145,8 @@ export class IgxPivotRowDimensionHeaderGroupComponent extends IgxGridHeaderGroup protected getHeaderWidthFromDimension() { if (this.grid.hasHorizontalLayout) { - return this.parent.width === -1 ? 'fit-content' : this.width; + // Collapsed and summary headers can span several columns. + return this.parent.width === -1 ? 'fit-content' : `${this.parent.width}px`; } return this.grid.rowDimensionWidth(this.parent.rootDimension); }