diff --git a/projects/igniteui-angular-performance/src/app/app.routes.ts b/projects/igniteui-angular-performance/src/app/app.routes.ts index 190c44ecdb4..5804152b12b 100644 --- a/projects/igniteui-angular-performance/src/app/app.routes.ts +++ b/projects/igniteui-angular-performance/src/app/app.routes.ts @@ -2,6 +2,7 @@ import { Routes } from '@angular/router'; import { GridComponent } from './grid/grid.component'; import { TreeGridComponent } from './tree-grid/tree-grid.component'; import { PivotGridComponent } from './pivot-grid/pivot-grid.component'; +import { HierarchicalGridComponent } from './hierarchical-grid/hierarchical-grid.component'; export const routes: Routes = [ { @@ -45,6 +46,12 @@ export const routes: Routes = [ pathMatch: 'full', component: GridComponent, data: { rows: 1000 } - } + }, + { + path: "hierarchical-grid-100k", + title: "Hierarchical Grid 100k records", + component: HierarchicalGridComponent, + data: { rows: 100_000 } + }, ]; diff --git a/projects/igniteui-angular-performance/src/app/hierarchical-grid/hierarchical-grid.component.html b/projects/igniteui-angular-performance/src/app/hierarchical-grid/hierarchical-grid.component.html new file mode 100644 index 00000000000..7c186c0982c --- /dev/null +++ b/projects/igniteui-angular-performance/src/app/hierarchical-grid/hierarchical-grid.component.html @@ -0,0 +1,35 @@ +
+ + @for (col of columns; track col) { + + + } + + @for (col of columns; track col) { + + + } + + +
diff --git a/projects/igniteui-angular-performance/src/app/hierarchical-grid/hierarchical-grid.component.scss b/projects/igniteui-angular-performance/src/app/hierarchical-grid/hierarchical-grid.component.scss new file mode 100644 index 00000000000..bc86bb4c9a3 --- /dev/null +++ b/projects/igniteui-angular-performance/src/app/hierarchical-grid/hierarchical-grid.component.scss @@ -0,0 +1,10 @@ +:host { + display: flex; + flex-direction: column; + height: 100%; +} + +.grid-wrapper { + height: 100%; + width: 100%; +} diff --git a/projects/igniteui-angular-performance/src/app/hierarchical-grid/hierarchical-grid.component.ts b/projects/igniteui-angular-performance/src/app/hierarchical-grid/hierarchical-grid.component.ts new file mode 100644 index 00000000000..a23f8a5bfa0 --- /dev/null +++ b/projects/igniteui-angular-performance/src/app/hierarchical-grid/hierarchical-grid.component.ts @@ -0,0 +1,39 @@ +import { Component, inject, ViewChild } from '@angular/core'; +import { GridColumnDataType, IgxColumnComponent, IgxHierarchicalGridComponent, IgxRowIslandComponent } from "igniteui-angular" +import { DataService } from '../services/data.service'; +import { ActivatedRoute } from '@angular/router'; + +@Component({ + selector: 'app-hierarchical-grid', + imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent], + templateUrl: './hierarchical-grid.component.html', + styleUrl: './hierarchical-grid.component.scss' +}) +export class HierarchicalGridComponent { + protected columns: any[] = [] + protected data: any[] = []; + protected performanceDataList: PerformanceEntryList = []; + private dataService = inject(DataService); + private activatedRoute = inject(ActivatedRoute); + + @ViewChild(IgxHierarchicalGridComponent, { static: true }) + public grid: IgxHierarchicalGridComponent; + + constructor() { + this.data = this.dataService.generateHierarchicalData(this.activatedRoute.snapshot.data.rows) + this.columns = [ + { field: "Id", dataType: GridColumnDataType.Number, sortable: true, width: 'auto', groupable: true }, + { field: "Name", dataType: GridColumnDataType.String, sortable: true, width: 'auto', groupable: true }, + { field: "AthleteNumber", dataType: GridColumnDataType.Number, sortable: true, width: 'auto', groupable: true }, + { field: "Registered", dataType: GridColumnDataType.DateTime, sortable: true, width: 'auto', groupable: true }, + { field: "CountryName", dataType: GridColumnDataType.String, sortable: true, width: 'auto', groupable: true }, + { field: "FirstAppearance", dataType: GridColumnDataType.Time, sortable: true, width: 'auto', groupable: true }, + { field: "CareerStart", dataType: GridColumnDataType.Date, sortable: true, width: 'auto', groupable: true }, + { field: "Active", dataType: GridColumnDataType.Boolean, sortable: true, width: 'auto', groupable: true }, + { field: "NetWorth", dataType: GridColumnDataType.Currency, sortable: true, width: 'auto', groupable: true }, + { field: "CountryFlag", dataType: GridColumnDataType.Image, sortable: true, width: 'auto', groupable: true }, + { field: "SuccessRate", dataType: GridColumnDataType.Percent, sortable: true, width: 'auto', groupable: true }, + { field: "Position", dataType: GridColumnDataType.String, sortable: true, width: 'auto', groupable: true }, + ]; + } +} diff --git a/projects/igniteui-angular-performance/src/app/services/data.service.ts b/projects/igniteui-angular-performance/src/app/services/data.service.ts index 2cda3cbf715..b598d85a9cb 100644 --- a/projects/igniteui-angular-performance/src/app/services/data.service.ts +++ b/projects/igniteui-angular-performance/src/app/services/data.service.ts @@ -16,6 +16,12 @@ export class DataService { return data; } + public generateHierarchicalData(rows: number): any[] { + const rnd = new Mulberry32(1234); + const data = this.generateAthletesData(rnd, rows, true); + return data; + } + public generateTreeData(rows: number): any[] { const rnd = new Mulberry32(1234); const data = this.generateEmployeesData(rnd, rows); @@ -114,7 +120,7 @@ export class DataService { return currData; } - private generateAthletesData(rnd: Mulberry32, rows: number): any[] { + private generateAthletesData(rnd: Mulberry32, rows: number, children = false): any[] { const currData = []; for (let i = 0; i < rows; i++) { const rand = Math.floor(rnd.random() * Math.floor(athletesData.length)); @@ -125,6 +131,10 @@ export class DataService { dataObj["Active"] = this.randomizeBoolean(rnd); dataObj["SuccessRate"] = this.randomizePercentage(rnd); dataObj["AthleteNumber"] = this.randomizeAthleteNumber(dataObj["AthleteNumber"], rnd); + if (children) { + const rnd = new Mulberry32(i); + dataObj["childData"] = this.generateAthletesData(rnd, 5); + } currData.push(dataObj); } return currData; diff --git a/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts b/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts index f50e55d78d2..572ea83cd2b 100644 --- a/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts +++ b/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts @@ -1,5 +1,5 @@ import { NgForOfContext } from '@angular/common'; -import { ChangeDetectorRef, ComponentRef, Directive, EmbeddedViewRef, EventEmitter, Input, IterableChanges, IterableDiffer, IterableDiffers, NgZone, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, TemplateRef, TrackByFunction, ViewContainerRef, AfterViewInit, booleanAttribute, DOCUMENT, inject, afterNextRender, runInInjectionContext, EnvironmentInjector } from '@angular/core'; +import { ChangeDetectorRef, ComponentRef, Directive, EmbeddedViewRef, EventEmitter, Input, IterableChanges, IterableDiffer, IterableDiffers, NgZone, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, TemplateRef, TrackByFunction, ViewContainerRef, booleanAttribute, DOCUMENT, inject, afterNextRender, runInInjectionContext, EnvironmentInjector, AfterViewInit } from '@angular/core'; import { DisplayContainerComponent } from './display.container'; import { HVirtualHelperComponent } from './horizontal.virtual.helper.component'; @@ -84,7 +84,7 @@ export abstract class IgxForOfToken { ], standalone: true }) -export class IgxForOfDirective extends IgxForOfToken implements OnInit, OnChanges, OnDestroy, AfterViewInit { +export class IgxForOfDirective extends IgxForOfToken implements OnInit, AfterViewInit, OnChanges, OnDestroy { private _viewContainer = inject(ViewContainerRef); protected _template = inject>>(TemplateRef); protected _differs = inject(IterableDiffers); @@ -95,6 +95,7 @@ export class IgxForOfDirective extends IgxForOfToken, number>(); /** * Sets the data to be rendered. @@ -274,6 +275,8 @@ export class IgxForOfDirective extends IgxForOfToken> = []; protected contentResizeNotify = new Subject(); protected contentObserver: ResizeObserver; + protected viewObserver: ResizeObserver; + protected viewResizeNotify = new Subject(); /** Size that is being virtualized. */ protected _virtSize = 0; /** @@ -389,10 +392,10 @@ export class IgxForOfDirective extends IgxForOfToken= because `scrollTop + container size` can't be bigger than `scrollHeight`, unless something isn't updated. // Also use Math.round because Chrome has some inconsistencies and `scrollTop + container` can be float when zooming the page. - return Math.round(this.getScroll().scrollTop + this.igxForContainerSize) === scrollHeight; + return Math.round(this.scrollComponent.scrollAmount + this.igxForContainerSize) === scrollHeight; } private get _isAtBottomIndex() { @@ -509,6 +512,17 @@ export class IgxForOfDirective extends IgxForOfToken { + if (this.platformUtil.isBrowser) { + this.viewObserver = new (getResizeObserver())((entries: ResizeObserverEntry[]) => this.viewResizeNotify.next(entries)); + this.viewObserver.observe(target); + } + }); + } + } + /** * @hidden */ @@ -819,35 +833,36 @@ export class IgxForOfDirective extends IgxForOfToken 5; } + /** * @hidden * Function that recalculates and updates cache sizes. */ - public recalcUpdateSizes() { + public recalcUpdateSizes(prevState?: IForOfState) { + if (prevState && prevState.startIndex === this.state.startIndex && prevState.chunkSize === this.state.chunkSize) { + // nothing changed + return; + } const dimension = this.igxForScrollOrientation === 'horizontal' ? - this.igxForSizePropName : 'height'; + this.igxForSizePropName : 'height'; const diffs = []; let totalDiff = 0; - const l = this._embeddedViews.length; const rNodes = this.embeddedViewNodes; - for (let i = 0; i < l; i++) { - const rNode = rNodes[i]; - if (rNode) { - const height = window.getComputedStyle(rNode).getPropertyValue('height'); - const h = parseFloat(height) || parseInt(this.igxForItemSize, 10); - const index = this.state.startIndex + i; - if (!this.isRemote && !this.igxForOf[index]) { - continue; - } - const margin = this.getMargin(rNode, dimension); - const oldVal = this.individualSizeCache[index]; - const newVal = (dimension === 'height' ? h : rNode.clientWidth) + margin; - this.individualSizeCache[index] = newVal; - const currDiff = newVal - oldVal; - diffs.push(currDiff); - totalDiff += currDiff; - this.sizesCache[index + 1] = (this.sizesCache[index] || 0) + newVal; - } + for (let index = 0; index < this._embeddedViews.length; index++) { + const rNode = rNodes[index]; + const targetIndex = this.state.startIndex + index; + const view = this._embeddedViews[index]; + const nodeSize = this._embeddedViewSizesCache.get(view) ?? + dimension === 'height' ? + rNode.clientHeight + this.getMargin(rNode, dimension): + rNode.clientWidth + this.getMargin(rNode, dimension); + const oldVal = this.individualSizeCache[targetIndex]; + const newVal = nodeSize; + const currDiff = newVal - oldVal; + diffs.push(currDiff); + totalDiff += currDiff; + this.individualSizeCache[targetIndex] = nodeSize; + this.sizesCache[targetIndex + 1] = (this.sizesCache[targetIndex] || 0) + newVal; } // update cache if (Math.abs(totalDiff) > 0) { @@ -972,6 +987,16 @@ export class IgxForOfDirective extends IgxForOfToken { + const index = parseInt(entry.target.getAttribute('data-index'), 0); + const height = entry.contentRect.height; + const embView = this._embeddedViews[index - this.state.startIndex]; + this._embeddedViewSizesCache.set(embView, height); + }); + this.recalcUpdateSizes(); + } + /** * @hidden */ @@ -1415,9 +1440,11 @@ export class IgxForOfDirective extends IgxForOfToken node.nodeType === Node.ELEMENT_NODE) || oldElem.rootNodes[0].nextElementSibling); // also detach from ViewContainerRef to make absolutely sure this is removed from the view container. this.dc.instance._vcr.detach(this.dc.instance._vcr.length - 1); oldElem.destroy(); + this._embeddedViewSizesCache.delete(oldElem); this.state.chunkSize--; } @@ -1499,7 +1526,6 @@ export class IgxForOfDirective extends IgxForOfToken 0 && this.scrollPosition > 0) { - this.recalcUpdateSizes(); const offset = this.igxForScrollOrientation === 'horizontal' ? parseInt(this.dc.instance._viewContainer.element.nativeElement.style.left, 10) : Number(this.dc.instance._viewContainer.element.nativeElement.style.transform?.match(/translateY\((-?\d+\.?\d*)px\)/)?.[1]); @@ -1598,9 +1624,9 @@ export class IgxGridForOfDirective extends IgxForOfDirec return this.igxForSizePropName || 'height'; } - public override recalcUpdateSizes() { + public override recalcUpdateSizes(prevState?: IForOfState) { if (this.igxGridForOfVariableSizes && this.igxForScrollOrientation === 'vertical') { - super.recalcUpdateSizes(); + super.recalcUpdateSizes(prevState); } } @@ -1627,6 +1653,12 @@ export class IgxGridForOfDirective extends IgxForOfDirec this.syncService.setMaster(this); super.ngOnInit(); this.removeScrollEventListeners(); + const destructor = takeUntil(this.destroy$); + this.viewObserver = new (getResizeObserver())((entries: ResizeObserverEntry[]) => this.viewResizeNotify.next(entries)); + this.viewResizeNotify.pipe( + filter(() => this.igxForContainerSize && this.igxForOf && this.igxForOf.length > 0), + destructor + ).subscribe((entries: ResizeObserverEntry[]) => () => this.updateViewSizes(entries)); } public override ngOnChanges(changes: SimpleChanges) { @@ -1714,12 +1746,13 @@ export class IgxGridForOfDirective extends IgxForOfDirec } else { this._bScrollInternal = false; } + const prevState = Object.assign({}, this.state); const scrollOffset = this.fixedUpdateAllElements(this._virtScrollPosition); runInInjectionContext(this._injector, () => { afterNextRender({ write: () => { this.dc.instance._viewContainer.element.nativeElement.style.transform = `translateY(${-scrollOffset}px)`; - this._zone.onStable.pipe(first()).subscribe(this.recalcUpdateSizes.bind(this)); + this._zone.onStable.pipe(first()).subscribe(this.recalcUpdateSizes.bind(this, prevState)); } }); }); @@ -1851,6 +1884,7 @@ export class IgxGridForOfDirective extends IgxForOfDirec ); this._embeddedViews.push(embeddedView); + this.subscribeToViewObserver(embeddedView.rootNodes.find(node => node.nodeType === Node.ELEMENT_NODE) || embeddedView.rootNodes[0].nextElementSibling); this.state.chunkSize++; } diff --git a/projects/igniteui-angular/grids/grid/src/cell.spec.ts b/projects/igniteui-angular/grids/grid/src/cell.spec.ts index 95d97bc6142..e3a0a9f5939 100644 --- a/projects/igniteui-angular/grids/grid/src/cell.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/cell.spec.ts @@ -185,14 +185,18 @@ describe('IgxGrid - Cell component #grid', () => { it('should fit last cell in the available display container when there is vertical and horizontal scroll.', (async () => { fix.componentInstance.columns = fix.componentInstance.generateCols(100); fix.componentInstance.data = fix.componentInstance.generateData(1000); - await wait(); + fix.detectChanges(); + await wait(16); fix.detectChanges(); const firsCell = GridFunctions.getRowCells(fix, 1)[0]; expect(GridFunctions.getValueFromCellElement(firsCell)).toEqual('0'); - fix.componentInstance.scrollLeft(999999); - await wait(); + const scrollbar = grid.headerContainer.getScroll(); + scrollbar.scrollLeft = 999999; + + await wait(16); + // This won't work always in debugging mode due to the angular native events behavior, so errors are expected fix.detectChanges(); const cells = GridFunctions.getRowCells(fix, 1); @@ -238,7 +242,7 @@ describe('IgxGrid - Cell component #grid', () => { const scrollbar = grid.headerContainer.getScroll(); scrollbar.scrollLeft = 10000; fix.detectChanges(); - await wait(); + await wait(16); const lastColumnCells = grid.columnList.get(grid.columnList.length - 1).cells; fix.detectChanges(); lastColumnCells.forEach((item) => { diff --git a/projects/igniteui-angular/grids/grid/src/grid.component.html b/projects/igniteui-angular/grids/grid/src/grid.component.html index 9e96d118d99..9efef0a7b42 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.component.html +++ b/projects/igniteui-angular/grids/grid/src/grid.component.html @@ -104,6 +104,7 @@ [igxForItemSize]="hasColumnLayouts ? rowHeight * multiRowLayoutRowSize + 1 : renderedRowHeight" [igxForTrackBy]="trackChanges" #verticalScrollContainer (chunkPreload)="dataLoading($event)" (dataChanging)="dataRebinding($event)" (dataChanged)="dataRebound($event)"> +
+
diff --git a/projects/igniteui-angular/grids/grid/src/grid.groupby.spec.ts b/projects/igniteui-angular/grids/grid/src/grid.groupby.spec.ts index 0087c32f4db..04c4918e841 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.groupby.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.groupby.spec.ts @@ -167,11 +167,11 @@ describe('IgxGrid - GroupBy #grid', () => { expect(groupRows.length).toEqual(4); expect(dataRows.length).toEqual(8); - const expectedValue1 = groupRows[1].nativeElement.nextElementSibling.querySelectorAll('igx-grid-cell')[3].textContent; + const expectedValue1 = groupRows[1].nativeElement.parentElement.nextElementSibling.querySelectorAll('igx-grid-cell')[3].textContent; const actualValue1 = groupRows[1].element.nativeElement.querySelector('.igx-group-label__text').textContent; - const expectedValue2 = groupRows[2].nativeElement.nextElementSibling.querySelectorAll('igx-grid-cell')[3].textContent; + const expectedValue2 = groupRows[2].nativeElement.parentElement.nextElementSibling.querySelectorAll('igx-grid-cell')[3].textContent; const actualValue2 = groupRows[2].element.nativeElement.querySelector('.igx-group-label__text').textContent; - const expectedValue3 = groupRows[3].nativeElement.nextElementSibling.querySelectorAll('igx-grid-cell')[3].textContent; + const expectedValue3 = groupRows[3].nativeElement.parentElement.nextElementSibling.querySelectorAll('igx-grid-cell')[3].textContent; const actualValue3 = groupRows[3].element.nativeElement.querySelector('.igx-group-label__text').textContent; expect(actualValue1).toEqual(expectedValue1); @@ -300,7 +300,7 @@ describe('IgxGrid - GroupBy #grid', () => { fix.detectChanges(); const groupRows = grid.groupsRowList.toArray(); - const expectedValue1 = groupRows[0].nativeElement.nextElementSibling.querySelectorAll('igx-grid-cell')[3].textContent; + const expectedValue1 = groupRows[0].nativeElement.parentElement.nextElementSibling.querySelectorAll('igx-grid-cell')[3].textContent; const actualValue1 = groupRows[0].element.nativeElement.querySelector('.igx-group-label__text').textContent; expect(expectedValue1).toEqual(actualValue1); })); @@ -317,7 +317,7 @@ describe('IgxGrid - GroupBy #grid', () => { fix.detectChanges(); const groupRows = grid.groupsRowList.toArray(); - const expectedValue1 = groupRows[0].nativeElement.nextElementSibling.querySelectorAll('igx-grid-cell')[4].textContent; + const expectedValue1 = groupRows[0].nativeElement.parentElement.nextElementSibling.querySelectorAll('igx-grid-cell')[4].textContent; const actualValue1 = groupRows[0].element.nativeElement.querySelector('.igx-group-label__text').textContent; expect(expectedValue1).toEqual(actualValue1); })); diff --git a/projects/igniteui-angular/grids/grid/src/grid.master-detail.spec.ts b/projects/igniteui-angular/grids/grid/src/grid.master-detail.spec.ts index 497caf776ae..95763354bd1 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.master-detail.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.master-detail.spec.ts @@ -479,7 +479,7 @@ describe('IgxGrid Master Detail #grid', () => { await wait(DEBOUNCE_TIME); fix.detectChanges(); - const detailRow = row.nativeElement.previousElementSibling as HTMLElement; + const detailRow = row.nativeElement.parentElement.previousElementSibling.children[0] as HTMLElement; GridFunctions.verifyMasterDetailRowFocused(detailRow); expect(GridFunctions.elementInGridView(grid, detailRow)).toBeTruthy(); }); @@ -499,7 +499,7 @@ describe('IgxGrid Master Detail #grid', () => { fix.detectChanges(); row = grid.gridAPI.get_row_by_index(2); - const detailRow = row.nativeElement.previousElementSibling as HTMLElement; + const detailRow = row.nativeElement.parentElement.previousElementSibling.children[0] as HTMLElement; GridFunctions.verifyMasterDetailRowFocused(detailRow); expect(GridFunctions.elementInGridView(grid, detailRow)).toBeTruthy(); }); @@ -1204,7 +1204,7 @@ describe('IgxGrid Master Detail #grid', () => { await wait(); fix.detectChanges(); - const allRows = grid.tbody.nativeElement.firstElementChild.children; + const allRows = [...grid.tbody.nativeElement.firstElementChild.children].map(x=> x.children[0]); expect(allRows.length).toBe(8); expect(allRows[0].tagName.toLowerCase()).toBe(GROUP_ROW_TAG); expect(allRows[1].tagName.toLowerCase()).toBe(ROW_TAG); @@ -1227,7 +1227,7 @@ describe('IgxGrid Master Detail #grid', () => { grid.summaryPosition = GridSummaryPosition.top; fix.detectChanges(); - const allRows = grid.tbody.nativeElement.firstElementChild.children; + const allRows = [...grid.tbody.nativeElement.firstElementChild.children].map(x=> x.children[0]); expect(allRows.length).toBe(8); expect(allRows[0].tagName.toLowerCase()).toBe(GROUP_ROW_TAG); expect(allRows[1].tagName.toLowerCase()).toBe(SUMMARY_ROW_TAG); @@ -1245,7 +1245,7 @@ describe('IgxGrid Master Detail #grid', () => { after grouping by and detail views for the group rows are collapsed.`, () => { grid.summaryPosition = GridSummaryPosition.top; fix.detectChanges(); - const allRows = grid.tbody.nativeElement.firstElementChild.children; + const allRows = [...grid.tbody.nativeElement.firstElementChild.children].map(x=> x.children[0]); expect(allRows.length).toBe(9); expect(allRows[0].tagName.toLowerCase()).toBe(GROUP_ROW_TAG); expect(allRows[1].tagName.toLowerCase()).toBe(SUMMARY_ROW_TAG); @@ -1260,7 +1260,7 @@ describe('IgxGrid Master Detail #grid', () => { it(`Should correctly position summary rows when summary row position is bottom after grouping by and detail views for the group rows are collapsed.`, () => { - const allRows = grid.tbody.nativeElement.firstElementChild.children; + const allRows = [...grid.tbody.nativeElement.firstElementChild.children].map(x=> x.children[0]); expect(allRows.length).toBe(9); expect(allRows[0].tagName.toLowerCase()).toBe(GROUP_ROW_TAG); expect(allRows[1].tagName.toLowerCase()).toBe(ROW_TAG); diff --git a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.component.html b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.component.html index e7683ef7c9b..5761a4e041a 100644 --- a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.component.html +++ b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.component.html @@ -82,11 +82,13 @@ [igxForScrollOrientation]="'vertical'" [igxForScrollContainer]="verticalScroll" [igxForContainerSize]="calcHeight" [igxForItemSize]="renderedRowHeight" [igxForTrackBy]="trackChanges" #verticalScrollContainer (chunkPreload)="dataLoading($event)" (dataChanging)="dataRebinding($event)" (dataChanged)="dataRebound($event)"> +
+
diff --git a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.html b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.html index 558cf1c4721..6833e93d665 100644 --- a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.html +++ b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.html @@ -44,11 +44,13 @@ [igxForItemSize]="hasColumnLayouts ? rowHeight * multiRowLayoutRowSize + 1 : renderedRowHeight" [igxGridForOfVariableSizes]="false" #verticalScrollContainer (dataChanging)="dataRebinding($event)" (dataChanged)="dataRebound($event)"> +
+
+
+
diff --git a/projects/igniteui-angular/test-utils/grid-functions.spec.ts b/projects/igniteui-angular/test-utils/grid-functions.spec.ts index a46159be685..bf0b8125a4d 100644 --- a/projects/igniteui-angular/test-utils/grid-functions.spec.ts +++ b/projects/igniteui-angular/test-utils/grid-functions.spec.ts @@ -208,7 +208,7 @@ export class GridFunctions { } public static getMasterRowDetail(row) { - const nextSibling = row.element.nativeElement.nextElementSibling; + const nextSibling = row.element.nativeElement.parentElement.nextElementSibling.children[0]; if (nextSibling && nextSibling.tagName.toLowerCase() === 'div' && nextSibling.getAttribute('detail') === 'true') { @@ -252,8 +252,8 @@ export class GridFunctions { public static getMasterRowDetailDebug(fix: ComponentFixture, row: IgxRowDirective) { const rowDE = fix.debugElement.queryAll(By.directive(IgxRowDirective)).find(el => el.componentInstance === row); - const detailDE = rowDE.parent.children - .find(el => el.attributes['detail'] === 'true' && el.attributes['data-rowindex'] === row.index + 1 + ''); + const detailDE = rowDE.parent.parent.children + .find(el => el.children[0].attributes['detail'] === 'true' && el.children[0].attributes['data-rowindex'] === row.index + 1 + ''); return detailDE; }