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,22 +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
} from '@angular/core';
import { AsyncPipe, NgClass, NgForOfContext } from '@angular/common';
import { AfterViewInit, ChangeDetectorRef, Component, Directive, Injectable, IterableDiffers, NgZone, OnInit, QueryList, TemplateRef, ViewChild, ViewChildren, ViewContainerRef, DebugElement, Pipe, PipeTransform, 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 @@ -1246,6 +1229,34 @@ describe('IgxForOf directive -', () => {
});
});

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

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

fix = TestBed.createComponent(VerticalVirtualComponent);
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();
});

});

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ import {
AfterViewInit,
Inject,
booleanAttribute,
DOCUMENT
DOCUMENT,
afterNextRender,
runInInjectionContext,
Injector,
inject
} from '@angular/core';

import { DisplayContainerComponent } from './display.container';
Expand Down Expand Up @@ -407,6 +411,8 @@ export class IgxForOfDirective<T, U extends T[] = T[]> extends IgxForOfToken<T,U
return this.igxForOf && this.state.startIndex + this.state.chunkSize > this.igxForOf.length;
}

protected readonly _injector = inject(Injector);

constructor(
private _viewContainer: ViewContainerRef,
protected _template: TemplateRef<NgForOfContext<T>>,
Expand Down Expand Up @@ -815,6 +821,10 @@ export class IgxForOfDirective<T, U extends T[] = T[]> extends IgxForOfToken<T,U
|| containerSize && endTopOffset - containerSize > 5;
}

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 @@ -925,10 +935,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();

this.dc.instance._viewContainer.element.nativeElement.style.top = -(scrollOffset) + 'px';

this._zone.onStable.pipe(first()).subscribe(this.recalcUpdateSizes.bind(this));
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 @@ -1121,7 +1142,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 @@ -1713,10 +1745,21 @@ export class IgxGridForOfDirective<T, U extends T[] = T[]> extends IgxForOfDirec
this._bScrollInternal = false;
}
const scrollOffset = this.fixedUpdateAllElements(this._virtScrollPosition);
const isZoneless = this.isZonelessChangeDetection();

this.dc.instance._viewContainer.element.nativeElement.style.top = -(scrollOffset) + 'px';

this._zone.onStable.pipe(first()).subscribe(this.recalcUpdateSizes.bind(this));
if (isZoneless) {
runInInjectionContext(this._injector, () => {
afterNextRender({
mixedReadWrite: () => {
this.recalcUpdateSizes();
}
});
});
} else {
this._zone.onStable.pipe(first()).subscribe(this.recalcUpdateSizes.bind(this));
}
this.cdr.markForCheck();
}

Expand Down
13 changes: 11 additions & 2 deletions projects/igniteui-angular/src/lib/grids/grid-base.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3806,7 +3806,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 @@ -3821,7 +3821,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 Expand Up @@ -4530,6 +4535,10 @@ export abstract class IgxGridBaseDirective implements GridType,
return this.elementRef.nativeElement;
}

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

/**
* Gets/Sets the outlet used to attach the grid's overlays to.
*
Expand Down
Loading