Skip to content

Commit 025932d

Browse files
authored
fix(for-of): correct virtualized sizing for bordered lists (#17496)
1 parent 433bb64 commit 025932d

4 files changed

Lines changed: 66 additions & 3 deletions

File tree

projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.spec.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,38 @@ describe('IgxForOf directive -', () => {
358358
expect(cache).toEqual([130, 100, 100, 100, 100, 100, 100, 130, 130, 130]);
359359
});
360360

361+
it('should take item borders and margins into account when calculating its size', () => {
362+
const virtualContainer = fix.componentInstance.parentVirtDir;
363+
const node = document.createElement('div');
364+
node.style.width = '100px';
365+
node.style.height = '80px';
366+
node.style.border = '2px solid transparent';
367+
node.style.margin = '3px 5px 7px 11px';
368+
fix.nativeElement.appendChild(node);
369+
370+
virtualContainer.igxForScrollOrientation = 'vertical';
371+
const verticalSize = node.getBoundingClientRect().height + 3 + 7;
372+
expect(virtualContainer.testGetNodeSize(node)).toBe(verticalSize);
373+
374+
virtualContainer.igxForScrollOrientation = 'horizontal';
375+
virtualContainer.igxForSizePropName = 'width';
376+
const horizontalSize = node.getBoundingClientRect().width + 5 + 11;
377+
expect(virtualContainer.testGetNodeSize(node)).toBe(horizontalSize);
378+
379+
node.remove();
380+
});
381+
382+
it('should preserve valid border sizes when another side cannot be parsed', () => {
383+
const virtualContainer = fix.componentInstance.parentVirtDir;
384+
const node = document.createElement('div');
385+
spyOn(window, 'getComputedStyle').and.returnValue({
386+
borderTopWidth: '',
387+
borderBottomWidth: '2px'
388+
} as CSSStyleDeclaration);
389+
390+
expect(virtualContainer.testGetBorder(node, 'height')).toBe(2);
391+
});
392+
361393
it('should render no more that initial chunk size elements when set if no containerSize', () => {
362394
fix.componentInstance.height = undefined;
363395
fix.componentInstance.initialChunkSize = 3;
@@ -1386,6 +1418,14 @@ export class TestIgxForOfDirective<T> extends IgxForOfDirective<T> {
13861418
public testGetHorizontalIndexAt(left, set) {
13871419
super.getIndexAt(left, set);
13881420
}
1421+
1422+
public testGetNodeSize(node: Element): number {
1423+
return super.getNodeSize(node, 0);
1424+
}
1425+
1426+
public testGetBorder(node: Element, dimension: string): number {
1427+
return super.getBorder(node, dimension);
1428+
}
13891429
}
13901430

13911431
/** Empty virtualized component */

projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -847,8 +847,8 @@ export class IgxForOfDirective<T, U extends T[] = T[]> extends IgxForOfToken<T,U
847847
const dimension = this.igxForScrollOrientation === 'horizontal' ?
848848
this.igxForSizePropName : 'height';
849849
const nodeSize = dimension === 'height' ?
850-
rNode.clientHeight + this.getMargin(rNode, dimension):
851-
rNode.clientWidth + this.getMargin(rNode, dimension);
850+
rNode.clientHeight + this.getBorder(rNode, dimension) + this.getMargin(rNode, dimension):
851+
rNode.clientWidth + this.getBorder(rNode, dimension) + this.getMargin(rNode, dimension);
852852
return nodeSize;
853853
}
854854

@@ -1565,6 +1565,16 @@ export class IgxForOfDirective<T, U extends T[] = T[]> extends IgxForOfToken<T,U
15651565
return parseFloat(styles['marginLeft']) +
15661566
parseFloat(styles['marginRight']) || 0;
15671567
}
1568+
1569+
protected getBorder(node, dimension: string): number {
1570+
const styles = window.getComputedStyle(node);
1571+
if (dimension === 'height') {
1572+
return (parseFloat(styles['borderTopWidth']) || 0) +
1573+
(parseFloat(styles['borderBottomWidth']) || 0);
1574+
}
1575+
return (parseFloat(styles['borderLeftWidth']) || 0) +
1576+
(parseFloat(styles['borderRightWidth']) || 0);
1577+
}
15681578
}
15691579

15701580
export const getTypeNameForDebugging = (type: any): string => type.name || typeof type;

projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-search.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ export class IgxExcelStyleSearchComponent implements AfterViewInit, OnDestroy {
362362
*/
363363
public get containerSize() {
364364
if (this.esf.listData.length) {
365-
return this.list?.element.nativeElement.offsetHeight;
365+
return this.list?.element.nativeElement.clientHeight;
366366
}
367367

368368
// GE Nov 1st, 2021 #10355 Return a numeric value, so the chunk size is calculated properly.

projects/igniteui-angular/grids/grid/src/grid-filtering-ui.spec.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4086,6 +4086,19 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => {
40864086
expect(listItems.length).toBe(6, 'incorrect rendered list items count');
40874087
});
40884088

4089+
it('Should use the list content height for the virtual container size', async () => {
4090+
GridFunctions.clickExcelFilterIconFromCodeAsync(fix, grid, 'ProductName');
4091+
fix.detectChanges();
4092+
await wait(100);
4093+
4094+
const searchComponent = fix.debugElement.query(By.css('igx-excel-style-search')).componentInstance;
4095+
const listElement = searchComponent.list.element.nativeElement as HTMLElement;
4096+
listElement.style.border = '1px solid transparent';
4097+
4098+
expect(listElement.offsetHeight).toBeGreaterThan(listElement.clientHeight);
4099+
expect(searchComponent.containerSize).toBe(listElement.clientHeight);
4100+
});
4101+
40894102
it('Should allow to input commas in excel search component input field when column dataType is number.', async () => {
40904103
GridFunctions.clickExcelFilterIconFromCodeAsync(fix, grid, 'Downloads');
40914104
fix.detectChanges();

0 commit comments

Comments
 (0)