Skip to content

Commit c9160e4

Browse files
authored
Merge pull request #7058 from IgniteUI/mkirova/fix-6893-8.2.x
fix(igxForOf): Add check in case scrollComponent is already destroyed.
2 parents 844f59f + f45dcf3 commit c9160e4

File tree

4 files changed

+89
-4
lines changed

4 files changed

+89
-4
lines changed

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

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import { IgxForOfSyncService, IgxForOfScrollSyncService } from './for_of.sync.se
2828

2929
describe('IgxForOf directive -', () => {
3030
const INACTIVE_VIRT_CONTAINER = 'igx-display-container--inactive';
31+
const DISPLAY_CONTAINER = 'igx-display-container';
32+
const VERTICAL_SCROLLER = 'igx-virtual-helper';
3133
let displayContainer: HTMLElement;
3234
let verticalScroller: HTMLElement;
3335
let horizontalScroller: HTMLElement;
@@ -202,6 +204,7 @@ describe('IgxForOf directive -', () => {
202204
horizontalScroller = fix.nativeElement.querySelector('igx-horizontal-virtual-helper');
203205
});
204206

207+
205208
it('should initialize directive with vertical virtualization', async () => {
206209
expect(displayContainer).not.toBeNull();
207210
expect(verticalScroller).not.toBeNull();
@@ -1140,6 +1143,55 @@ describe('IgxForOf directive -', () => {
11401143

11411144
});
11421145

1146+
describe('on destroy', () => {
1147+
let fix: ComponentFixture<VerticalVirtualDestroyComponent>;
1148+
1149+
configureTestSuite();
1150+
beforeAll(async(() => {
1151+
TestBed.configureTestingModule({
1152+
declarations: [
1153+
TestIgxForOfDirective,
1154+
VerticalVirtualDestroyComponent
1155+
],
1156+
imports: [IgxForOfModule]
1157+
}).compileComponents();
1158+
}));
1159+
1160+
beforeEach(() => {
1161+
fix = TestBed.createComponent(VerticalVirtualDestroyComponent);
1162+
fix.componentInstance.data = dg.generateVerticalData(fix.componentInstance.cols);
1163+
fix.componentRef.hostView.detectChanges();
1164+
fix.detectChanges();
1165+
});
1166+
it('should reset scroll position if component is destroyed and recreated.', async () => {
1167+
let scrollComponent = fix.debugElement.query(By.css(VERTICAL_SCROLLER)).componentInstance;
1168+
expect(scrollComponent.scrollAmount).toBe(0);
1169+
expect(scrollComponent.destroyed).toBeFalsy();
1170+
1171+
scrollComponent.nativeElement.scrollTop = 500;
1172+
fix.detectChanges();
1173+
await wait();
1174+
expect(scrollComponent.scrollAmount).toBe(500);
1175+
1176+
fix.componentInstance.exists = false;
1177+
fix.detectChanges();
1178+
await wait();
1179+
1180+
expect(scrollComponent.destroyed).toBeTruthy();
1181+
1182+
fix.componentInstance.exists = true;
1183+
fix.detectChanges();
1184+
await wait();
1185+
1186+
scrollComponent = fix.debugElement.query(By.css(VERTICAL_SCROLLER)).componentInstance;
1187+
expect(scrollComponent.scrollAmount).toBe(0);
1188+
expect(scrollComponent.destroyed).toBeFalsy();
1189+
1190+
displayContainer = fix.nativeElement.querySelector(DISPLAY_CONTAINER);
1191+
const firstInnerDisplayContainer = displayContainer.children[0];
1192+
expect(firstInnerDisplayContainer.children[0].textContent).toBe('0');
1193+
});
1194+
});
11431195
});
11441196

11451197
class DataGenerator {
@@ -1455,10 +1507,42 @@ export class VirtualComponent {
14551507
*/
14561508
return horizontalScrollbar.offsetHeight >= 16;
14571509
}
1510+
}
14581511

1459-
1512+
@Component({
1513+
template: `
1514+
<div *ngIf='exists' #container [style.width]='width' [style.height]='height'>
1515+
<ng-template #scrollContainer igxForTest let-rowData [igxForOf]="data"
1516+
[igxForScrollOrientation]="'vertical'"
1517+
[igxForContainerSize]='height'
1518+
[igxForItemSize]='itemSize'>
1519+
<div [style.display]="'flex'" [style.height]="rowData.height || itemSize || '50px'">
1520+
<div [style.min-width]=cols[0].width>{{rowData['1']}}</div>
1521+
<div [style.min-width]=cols[1].width>{{rowData['2']}}</div>
1522+
<div [style.min-width]=cols[2].width>{{rowData['3']}}</div>
1523+
<div [style.min-width]=cols[3].width>{{rowData['4']}}</div>
1524+
<div [style.min-width]=cols[4].width>{{rowData['5']}}</div>
1525+
</div>
1526+
</ng-template>
1527+
</div>
1528+
`
1529+
})
1530+
export class VerticalVirtualDestroyComponent {
1531+
public width = '450px';
1532+
public height = '300px';
1533+
public cols = [
1534+
{ field: '1', width: '150px' },
1535+
{ field: '2', width: '70px' },
1536+
{ field: '3', width: '50px' },
1537+
{ field: '4', width: '80px' },
1538+
{ field: '5', width: '100px' }
1539+
];
1540+
public data = [];
1541+
public itemSize = '50px';
1542+
public exists = true;
14601543
}
14611544

1545+
14621546
/** Only vertically virtualized component */
14631547
@Component({
14641548
template: `

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ export class IgxForOfDirective<T> implements OnInit, OnChanges, DoCheck, OnDestr
375375
this.scrollComponent = this.syncScrollService.getScrollMaster(this.igxForScrollOrientation);
376376
this.state.chunkSize = this._calculateChunkSize();
377377
this.dc.instance.notVirtual = !(this.igxForContainerSize && this.state.chunkSize < this.igxForOf.length);
378-
if (this.scrollComponent) {
378+
if (this.scrollComponent && !this.scrollComponent.destroyed) {
379379
this.state.startIndex = Math.min(this.getIndexAt(this.scrollPosition, this.sizesCache, 0),
380380
this.igxForOf.length - this.state.chunkSize);
381381
}

src/app/list-performance/list-performance.sample.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ <h4 class="sample-title">Performance sample</h4>
1313
<igx-icon>clear</igx-icon>
1414
</igx-suffix>
1515
</igx-input-group>
16-
16+
<button igxButton (click)='showList = !showList'>Toggle List</button>
1717
<igx-card>
18-
<igx-list>
18+
<igx-list *ngIf='showList'>
1919
<igx-list-item [isHeader]="true">Contacts</igx-list-item>
2020
<div class="virtualized-items" [style.height]="'500px'" [style.overflow]="'hidden'" [style.position]="'relative'">
2121
<igx-list-item igxRipple="pink" igxRippleTarget=".igx-list__item" *igxFor="let item of data | igxFilter: fo1; scrollOrientation : 'vertical'; containerSize: '500px'; itemSize: '56px'">

src/app/list-performance/list-performance.sample.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { IgxFilterOptions } from 'igniteui-angular';
99
export class ListPerformanceSampleComponent {
1010
search1: string;
1111
options = {};
12+
showList = true;
1213

1314
data = [{
1415
key: 1,

0 commit comments

Comments
 (0)