Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AsyncPipe, NgClass, NgForOfContext } from '@angular/common';
import { AfterViewInit, ChangeDetectorRef, Component, Directive, Injectable, IterableDiffers, NgZone, OnInit, QueryList, TemplateRef, ViewChild, ViewChildren, ViewContainerRef, DebugElement, Pipe, PipeTransform, inject } from '@angular/core';
import { AfterViewInit, ChangeDetectorRef, Component, Directive, Injectable, IterableDiffers, NgZone, OnInit, QueryList, TemplateRef, ViewChild, ViewChildren, ViewContainerRef, DebugElement, Pipe, PipeTransform, inject, provideZonelessChangeDetection } from '@angular/core';
import { TestBed, ComponentFixture, waitForAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { BehaviorSubject, Observable } from 'rxjs';
Expand Down Expand Up @@ -1230,6 +1230,45 @@ describe('IgxForOf directive -', () => {
});
});

describe('zoneless', () => {
let fix: ComponentFixture<VirtualComponent>;

beforeEach(async () => {
TestBed.resetTestingModule();
await TestBed.configureTestingModule({
imports: [VirtualComponent],
providers: [provideZonelessChangeDetection()]
}).compileComponents();

fix = TestBed.createComponent(VirtualComponent);
dg.generateData(300, 5, fix.componentInstance);
fix.detectChanges();
});

it('should call recalcUpdateSizes after vertical scroll', async () => {
const virtDir = fix.componentInstance.parentVirtDir;
const spy = spyOn(virtDir, 'recalcUpdateSizes').and.callThrough();

fix.componentInstance.scrollTop(300);
await wait(100);
fix.detectChanges();

expect(spy).toHaveBeenCalled();
});

it('should call recalcUpdateSizes after horizontal scroll', async () => {
const childDirs = fix.componentInstance.childVirtDirs.toArray();
const spy = spyOn(childDirs[0], 'recalcUpdateSizes').and.callThrough();

fix.componentInstance.scrollLeft(500);
await wait(100);
fix.detectChanges();

expect(spy).toHaveBeenCalled();
});

});

describe('on create new instance', () => {
let fix: ComponentFixture<VerticalVirtualCreateComponent>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,10 @@ export class IgxForOfDirective<T, U extends T[] = T[]> extends IgxForOfToken<T,U
}


protected isZonelessChangeDetection(): boolean {
return this._zone.constructor.name === 'NoopNgZone';
}
Comment thread
viktorkombov marked this conversation as resolved.

/**
* @hidden
* Function that recalculates and updates cache sizes.
Expand Down Expand Up @@ -960,16 +964,21 @@ export class IgxForOfDirective<T, U extends T[] = T[]> extends IgxForOfToken<T,U
}
const prevStartIndex = this.state.startIndex;
const scrollOffset = this.fixedUpdateAllElements(this._virtScrollPosition);
const isZoneless = this.isZonelessChangeDetection();

runInInjectionContext(this._injector, () => {
afterNextRender({
write: () => {
this.dc.instance._viewContainer.element.nativeElement.style.transform = `translateY(${-scrollOffset}px)`;
}
},
mixedReadWrite: isZoneless ? () => {
this.recalcUpdateSizes();
} : undefined
});
});

this._zone.onStable.pipe(first()).subscribe(this.recalcUpdateSizes.bind(this));
if (!isZoneless) {
this._zone.onStable.pipe(first()).subscribe(this.recalcUpdateSizes.bind(this));
}

this.dc.changeDetectorRef.detectChanges();
if (prevStartIndex !== this.state.startIndex) {
Expand Down Expand Up @@ -1175,7 +1184,18 @@ export class IgxForOfDirective<T, U extends T[] = T[]> extends IgxForOfToken<T,U
} else {
this.dc.instance._viewContainer.element.nativeElement.style.left = -scrollOffset + 'px';
}
this._zone.onStable.pipe(first()).subscribe(this.recalcUpdateSizes.bind(this));
const isZoneless = this.isZonelessChangeDetection();
if (isZoneless) {
runInInjectionContext(this._injector, () => {
afterNextRender({
mixedReadWrite: () => {
this.recalcUpdateSizes();
}
});
});
} else {
this._zone.onStable.pipe(first()).subscribe(this.recalcUpdateSizes.bind(this));
}

this.dc.changeDetectorRef.detectChanges();
if (prevStartIndex !== this.state.startIndex) {
Expand Down Expand Up @@ -1777,12 +1797,18 @@ export class IgxGridForOfDirective<T, U extends T[] = T[]> extends IgxForOfDirec
}
const prevState = Object.assign({}, this.state);
const scrollOffset = this.fixedUpdateAllElements(this._virtScrollPosition);
const isZoneless = this.isZonelessChangeDetection();
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, prevState));
}
if (!isZoneless) {
this._zone.onStable.pipe(first()).subscribe(this.recalcUpdateSizes.bind(this, prevState));
}
},
mixedReadWrite: isZoneless ? () => {
this.recalcUpdateSizes(prevState);
} : undefined
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3733,7 +3733,7 @@ export abstract class IgxGridBaseDirective implements GridType,
destructor
)
.subscribe(() => {
this.zone.run(() => {
const work = () => {
// do not trigger reflow if element is detached.
if (this.nativeElement.isConnected) {
if (this.shouldResize) {
Expand All @@ -3748,7 +3748,12 @@ export abstract class IgxGridBaseDirective implements GridType,
}
this.notifyChanges(true);
}
});
};
if (this.isZonelessChangeDetection()) {
work();
} else {
this.zone.run(work);
}
});

this.pipeTriggerNotifier.pipe(takeUntil(this.destroy$)).subscribe(() => this.pipeTrigger++);
Expand Down
Loading