From bd22a61c521f2386e91a14bed7d2a74486a63049 Mon Sep 17 00:00:00 2001 From: MKirova Date: Fri, 31 Oct 2025 18:39:32 +0200 Subject: [PATCH 1/5] fix(Grid): Add better handling for fraction numbers, as result of zoom. --- .../lib/directives/for-of/for_of.directive.ts | 62 +++++++++---------- .../src/lib/grids/grid-base.directive.ts | 5 +- .../pivot-grid/pivot-grid.component.html | 2 +- 3 files changed, 35 insertions(+), 34 deletions(-) diff --git a/projects/igniteui-angular/src/lib/directives/for-of/for_of.directive.ts b/projects/igniteui-angular/src/lib/directives/for-of/for_of.directive.ts index de6c031eede..2bd8da7ce7a 100644 --- a/projects/igniteui-angular/src/lib/directives/for-of/for_of.directive.ts +++ b/projects/igniteui-angular/src/lib/directives/for-of/for_of.directive.ts @@ -423,7 +423,7 @@ export class IgxForOfDirective extends IgxForOfToken parseInt(this.igxForContainerSize, 10); + return this.scrollComponent.size > parseFloat(this.igxForContainerSize); } /** @@ -556,8 +556,8 @@ export class IgxForOfDirective extends IgxForOfToken extends IgxForOfToken extends IgxForOfToken extends IgxForOfToken (this.isRemote ? this.totalItemCount : this.igxForOf.length) - 1) { return; } - const containerSize = parseInt(this.igxForContainerSize, 10); + const containerSize = parseFloat(this.igxForContainerSize); const isPrevItem = index < this.state.startIndex || this.scrollPosition > this.sizesCache[index]; let nextScroll = isPrevItem ? this.sizesCache[index] : this.sizesCache[index + 1] - containerSize; if (nextScroll < 0) { @@ -684,7 +684,7 @@ export class IgxForOfDirective extends IgxForOfToken extends IgxForOfToken extends IgxForOfToken extends IgxForOfToken extends IgxForOfToken extends IgxForOfToken view.rootNodes.find(node => node.nodeType === Node.ELEMENT_NODE) || view.rootNodes[0].nextElementSibling)[index - this.state.startIndex] : null; const rowHeight = this.getSizeAt(index); - const containerSize = parseInt(this.igxForContainerSize, 10); + const containerSize = parseFloat(this.igxForContainerSize); const containerOffset = -(this.scrollPosition - this.sizesCache[this.state.startIndex]); const endTopOffset = targetNode ? targetNode.offsetTop + rowHeight + containerOffset : containerSize + rowHeight; return !targetNode || targetNode.offsetTop < Math.abs(containerOffset) @@ -828,7 +828,7 @@ export class IgxForOfDirective extends IgxForOfToken extends IgxForOfToken extends IgxForOfToken extends IgxForOfToken extends IgxForOfToken extends IgxForOfToken extends IgxForOfToken containerSizeInfo.prevSize : this.isScrollable(); if (this.igxForScrollOrientation === 'horizontal') { - const totalWidth = parseInt(this.igxForContainerSize, 10) > 0 ? this._calcSize() : 0; - if (totalWidth <= parseInt(this.igxForContainerSize, 10)) { + const totalWidth = parseFloat(this.igxForContainerSize) > 0 ? this._calcSize() : 0; + if (totalWidth <= parseFloat(this.igxForContainerSize)) { this.resetScrollPosition(); } this.scrollComponent.nativeElement.style.width = this.igxForContainerSize + 'px'; @@ -1358,10 +1358,10 @@ export class IgxForOfDirective extends IgxForOfToken extends IgxForOfToken extends IgxForOfToken extends IgxForOfToken 0 && this.scrollPosition > 0) { this.recalcUpdateSizes(); const offset = this.igxForScrollOrientation === 'horizontal' ? - parseInt(this.dc.instance._viewContainer.element.nativeElement.style.left, 10) : - parseInt(this.dc.instance._viewContainer.element.nativeElement.style.top, 10); + parseFloat(this.dc.instance._viewContainer.element.nativeElement.style.left) : + parseFloat(this.dc.instance._viewContainer.element.nativeElement.style.top); const newSize = this.sizesCache[this.state.startIndex] - offset; this.scrollPosition = newSize; if (this.scrollPosition !== newSize) { @@ -1651,8 +1651,8 @@ export class IgxGridForOfDirective extends IgxForOfDirec } const containerSize = 'igxForContainerSize'; if (containerSize in changes && !changes[containerSize].firstChange && this.igxForOf) { - const prevSize = parseInt(changes[containerSize].previousValue, 10); - const newSize = parseInt(changes[containerSize].currentValue, 10); + const prevSize = parseFloat(changes[containerSize].previousValue); + const newSize = parseFloat(changes[containerSize].currentValue); this._recalcOnContainerChange({prevSize, newSize}); } } @@ -1700,7 +1700,7 @@ export class IgxGridForOfDirective extends IgxForOfDirec } public override onScroll(event) { - if (!parseInt(this.scrollComponent.nativeElement.style.height, 10)) { + if (!parseFloat(this.scrollComponent.nativeElement.style.height)) { return; } if (!this._bScrollInternal) { @@ -1719,7 +1719,7 @@ export class IgxGridForOfDirective extends IgxForOfDirec public override onHScroll(scrollAmount) { /* in certain situations this may be called when no scrollbar is visible */ const firstScrollChild = this.scrollComponent.nativeElement.children.item(0) as HTMLElement; - if (!this.scrollComponent || !parseInt(firstScrollChild.style.width, 10)) { + if (!this.scrollComponent || !parseFloat(firstScrollChild.style.width)) { return; } // Updating horizontal chunks @@ -1744,7 +1744,7 @@ export class IgxGridForOfDirective extends IgxForOfDirec size = item.height; } } else { - size = parseInt(item[dimension], 10) || 0; + size = parseFloat(item[dimension]) || 0; } return size; } diff --git a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts index 6df50fdef02..1d61e28449b 100644 --- a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts +++ b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts @@ -5632,7 +5632,7 @@ export abstract class IgxGridBaseDirective implements GridType, if (this.hasCellsToMerge) { return this.rowHeight; } - return this.rowHeight + 1; + return this.rowHeight; } /** @@ -8142,8 +8142,9 @@ export abstract class IgxGridBaseDirective implements GridType, protected updateDefaultRowHeight() { if (this.dataRowList.length > 0 && this.dataRowList.first.cells && this.dataRowList.first.cells.length > 0) { - const height = parseFloat(this.document.defaultView.getComputedStyle(this.dataRowList.first.cells.first.nativeElement)?.getPropertyValue('height')); + const height = parseFloat(this.document.defaultView.getComputedStyle(this.dataRowList.first.nativeElement)?.getPropertyValue('height')); if (height) { + console.log(height); this._defaultRowHeight = height; } else { this._shouldRecalcRowHeight = true; diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.component.html b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.component.html index 558cf1c4721..01e48c2269f 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.component.html +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.component.html @@ -42,7 +42,7 @@ let-rowIndex="index" [igxForScrollOrientation]="'vertical'" [igxForScrollContainer]="verticalScroll" [igxForContainerSize]="calcHeight" [igxForItemSize]="hasColumnLayouts ? rowHeight * multiRowLayoutRowSize + 1 : renderedRowHeight" - [igxGridForOfVariableSizes]="false" + #verticalScrollContainer (dataChanging)="dataRebinding($event)" (dataChanged)="dataRebound($event)"> Date: Fri, 31 Oct 2025 18:40:42 +0200 Subject: [PATCH 2/5] chore(*): Remove leftover console.log. --- projects/igniteui-angular/src/lib/grids/grid-base.directive.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts index 1d61e28449b..c4da9fc41ea 100644 --- a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts +++ b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts @@ -8144,7 +8144,6 @@ export abstract class IgxGridBaseDirective implements GridType, if (this.dataRowList.length > 0 && this.dataRowList.first.cells && this.dataRowList.first.cells.length > 0) { const height = parseFloat(this.document.defaultView.getComputedStyle(this.dataRowList.first.nativeElement)?.getPropertyValue('height')); if (height) { - console.log(height); this._defaultRowHeight = height; } else { this._shouldRecalcRowHeight = true; From aa86b81f939daba4da30e12fa8cabfbc6a08dfb7 Mon Sep 17 00:00:00 2001 From: MKirova Date: Wed, 5 Nov 2025 14:00:13 +0200 Subject: [PATCH 3/5] chore(*): Remove renderedActualRowHeight, since we now measure whole row. --- .../src/lib/grids/grid-base.directive.ts | 16 ++-------------- .../src/lib/grids/grid/grid.component.ts | 2 +- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts index c4da9fc41ea..7892472caf1 100644 --- a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts +++ b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts @@ -3363,7 +3363,7 @@ export abstract class IgxGridBaseDirective implements GridType, private _sortAscendingHeaderIconTemplate: TemplateRef = null; private _sortDescendingHeaderIconTemplate: TemplateRef = null; private _gridSize: Size = Size.Large; - private _defaultRowHeight = 50; + private _defaultRowHeight = 51; private _rowCount: number; private _cellMergeMode: GridCellMergeMode = GridCellMergeMode.onSort; private _columnsToMerge: IgxColumnComponent[] = []; @@ -5620,7 +5620,7 @@ export abstract class IgxGridBaseDirective implements GridType, */ protected get defaultTargetBodyHeight(): number { const allItems = this.dataLength; - return this.renderedActualRowHeight * Math.min(this._defaultTargetRecordNumber, + return this.renderedRowHeight * Math.min(this._defaultTargetRecordNumber, this.paginator ? Math.min(allItems, this.paginator.perPage) : allItems); } @@ -5629,9 +5629,6 @@ export abstract class IgxGridBaseDirective implements GridType, * The rowHeight input is bound to min-height css prop of rows that adds a 1px border in all cases */ public get renderedRowHeight(): number { - if (this.hasCellsToMerge) { - return this.rowHeight; - } return this.rowHeight; } @@ -7870,15 +7867,6 @@ export abstract class IgxGridBaseDirective implements GridType, this.gridScroll.emit(args); } - protected get renderedActualRowHeight() { - let border = 1; - if (this.rowList.toArray().length > 0) { - const rowStyles = this.document.defaultView.getComputedStyle(this.rowList.first.nativeElement); - border = rowStyles.borderBottomWidth ? Math.ceil(parseFloat(rowStyles.borderBottomWidth)) : border; - } - return this.rowHeight + border; - } - private executeCallback(rowIndex, visibleColIndex = -1, cb: (args: any) => void = null) { if (!cb) { return; diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid.component.ts b/projects/igniteui-angular/src/lib/grids/grid/grid.component.ts index 55cd3e61f00..964275f35b7 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid.component.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid.component.ts @@ -1281,7 +1281,7 @@ export class IgxGridComponent extends IgxGridBaseDirective implements GridType, */ protected override get defaultTargetBodyHeight(): number { const allItems = this.totalItemCount || this.dataLength; - return this.renderedActualRowHeight * Math.min(this._defaultTargetRecordNumber, + return this.renderedRowHeight * Math.min(this._defaultTargetRecordNumber, this.paginator ? Math.min(allItems, this.perPage) : allItems); } From f646c619d27c8f5fcfa289fb2058e4d80b4d2b23 Mon Sep 17 00:00:00 2001 From: MKirova Date: Wed, 5 Nov 2025 14:58:16 +0200 Subject: [PATCH 4/5] chore(*): Fix by calculating border separately. --- .../src/lib/grids/grid-base.directive.ts | 23 +++++++++++++++---- .../src/lib/grids/grid/grid.component.ts | 2 +- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts index 7892472caf1..b5011824b11 100644 --- a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts +++ b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts @@ -3363,7 +3363,8 @@ export abstract class IgxGridBaseDirective implements GridType, private _sortAscendingHeaderIconTemplate: TemplateRef = null; private _sortDescendingHeaderIconTemplate: TemplateRef = null; private _gridSize: Size = Size.Large; - private _defaultRowHeight = 51; + private _defaultRowHeight = 50; + private _borderSize = 1; private _rowCount: number; private _cellMergeMode: GridCellMergeMode = GridCellMergeMode.onSort; private _columnsToMerge: IgxColumnComponent[] = []; @@ -5620,7 +5621,7 @@ export abstract class IgxGridBaseDirective implements GridType, */ protected get defaultTargetBodyHeight(): number { const allItems = this.dataLength; - return this.renderedRowHeight * Math.min(this._defaultTargetRecordNumber, + return this.renderedActualRowHeight * Math.min(this._defaultTargetRecordNumber, this.paginator ? Math.min(allItems, this.paginator.perPage) : allItems); } @@ -5629,7 +5630,10 @@ export abstract class IgxGridBaseDirective implements GridType, * The rowHeight input is bound to min-height css prop of rows that adds a 1px border in all cases */ public get renderedRowHeight(): number { - return this.rowHeight; + if (this.hasCellsToMerge) { + return this.rowHeight; + } + return this.rowHeight + this._borderSize; } /** @@ -7867,6 +7871,10 @@ export abstract class IgxGridBaseDirective implements GridType, this.gridScroll.emit(args); } + protected get renderedActualRowHeight() { + return this.rowHeight + this._borderSize; + } + private executeCallback(rowIndex, visibleColIndex = -1, cb: (args: any) => void = null) { if (!cb) { return; @@ -8130,12 +8138,19 @@ export abstract class IgxGridBaseDirective implements GridType, protected updateDefaultRowHeight() { if (this.dataRowList.length > 0 && this.dataRowList.first.cells && this.dataRowList.first.cells.length > 0) { - const height = parseFloat(this.document.defaultView.getComputedStyle(this.dataRowList.first.nativeElement)?.getPropertyValue('height')); + const height = parseFloat(this.document.defaultView.getComputedStyle(this.dataRowList.first.cells.first.nativeElement)?.getPropertyValue('height')); if (height) { this._defaultRowHeight = height; } else { this._shouldRecalcRowHeight = true; } + + const rowStyles = this.document.defaultView.getComputedStyle(this.dataRowList.first.nativeElement); + + const border = rowStyles.borderBottomWidth ? parseFloat(rowStyles.borderBottomWidth) : 1; + if (border) { + this._borderSize = border; + } } } diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid.component.ts b/projects/igniteui-angular/src/lib/grids/grid/grid.component.ts index 964275f35b7..55cd3e61f00 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid.component.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid.component.ts @@ -1281,7 +1281,7 @@ export class IgxGridComponent extends IgxGridBaseDirective implements GridType, */ protected override get defaultTargetBodyHeight(): number { const allItems = this.totalItemCount || this.dataLength; - return this.renderedRowHeight * Math.min(this._defaultTargetRecordNumber, + return this.renderedActualRowHeight * Math.min(this._defaultTargetRecordNumber, this.paginator ? Math.min(allItems, this.perPage) : allItems); } From 9ef60f374e5be04d42350e05b9987ffa35349252 Mon Sep 17 00:00:00 2001 From: MKirova Date: Wed, 5 Nov 2025 15:29:08 +0200 Subject: [PATCH 5/5] chore(*): Adjust test to not compare to hardcoded value. --- .../src/lib/grids/grid/grid.multi-row-layout.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid.multi-row-layout.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid.multi-row-layout.spec.ts index cbaee4b0fcd..d54ab05e8cf 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid.multi-row-layout.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid.multi-row-layout.spec.ts @@ -940,7 +940,7 @@ describe('IgxGrid - multi-row-layout #grid', () => { // check group size is correct expect(horizontalVirtualization.getSizeAt(0)).toBe(700); - expect(horizontalVirtualization.getSizeAt(1)).toBe(300); + expect(horizontalVirtualization.getSizeAt(1)).toBe(grid.calcWidth * 0.5); // check DOM gridFirstRow = grid.rowList.first; @@ -968,7 +968,7 @@ describe('IgxGrid - multi-row-layout #grid', () => { // check group size is correct expect(horizontalVirtualization.getSizeAt(0)).toBe(700); - expect(horizontalVirtualization.getSizeAt(1)).toBe(300); + expect(horizontalVirtualization.getSizeAt(1)).toBe(grid.calcWidth * 0.5); expect(horizontalVirtualization.getSizeAt(2)).toBe(136 * 4); // check DOM