From b1b2d3d634a138ce6419cae9161c16d36fd5cc07 Mon Sep 17 00:00:00 2001 From: Tiberiu Zuld Date: Mon, 17 Jun 2024 07:37:49 +0300 Subject: [PATCH] chore: zoneless working (#917) Co-authored-by: banned007 --- angular.json | 11 -- .../src/lib/gridster.component.ts | 4 +- .../src/lib/gridster.interface.ts | 3 +- .../src/lib/gridsterDraggable.service.ts | 36 +++--- .../src/lib/gridsterEmptyCell.service.ts | 34 +++-- .../src/lib/gridsterItem.component.ts | 8 +- .../src/lib/gridsterResizable.service.ts | 117 +++++++----------- src/app/app.config.ts | 5 +- 8 files changed, 84 insertions(+), 134 deletions(-) diff --git a/angular.json b/angular.json index c88c5538..a7e28edd 100644 --- a/angular.json +++ b/angular.json @@ -19,9 +19,6 @@ "options": { "outputPath": "dist/demo", "index": "src/index.html", - "polyfills": [ - "zone.js" - ], "tsConfig": "tsconfig.app.json", "assets": [ "src/assets" @@ -78,10 +75,6 @@ "test": { "builder": "@angular-devkit/build-angular:karma", "options": { - "polyfills": [ - "zone.js", - "zone.js/testing" - ], "tsConfig": "tsconfig.spec.json", "assets": [ "src/assets" @@ -141,10 +134,6 @@ "builder": "@angular-devkit/build-angular:karma", "options": { "tsConfig": "projects/angular-gridster2/tsconfig.spec.json", - "polyfills": [ - "zone.js", - "zone.js/testing" - ] } }, "lint": { diff --git a/projects/angular-gridster2/src/lib/gridster.component.ts b/projects/angular-gridster2/src/lib/gridster.component.ts index 07a0562d..a893bc5f 100644 --- a/projects/angular-gridster2/src/lib/gridster.component.ts +++ b/projects/angular-gridster2/src/lib/gridster.component.ts @@ -6,7 +6,6 @@ import { EventEmitter, Inject, Input, - NgZone, OnChanges, OnDestroy, OnInit, @@ -72,8 +71,7 @@ export class GridsterComponent constructor( @Inject(ElementRef) el: ElementRef, @Inject(Renderer2) public renderer: Renderer2, - @Inject(ChangeDetectorRef) public cdRef: ChangeDetectorRef, - @Inject(NgZone) public zone: NgZone + @Inject(ChangeDetectorRef) public cdRef: ChangeDetectorRef ) { this.el = el.nativeElement; this.$options = JSON.parse(JSON.stringify(GridsterConfigService)); diff --git a/projects/angular-gridster2/src/lib/gridster.interface.ts b/projects/angular-gridster2/src/lib/gridster.interface.ts index 31d98e41..2840253f 100644 --- a/projects/angular-gridster2/src/lib/gridster.interface.ts +++ b/projects/angular-gridster2/src/lib/gridster.interface.ts @@ -1,5 +1,5 @@ import { GridsterConfigS } from './gridsterConfigS.interface'; -import { ChangeDetectorRef, NgZone, Renderer2 } from '@angular/core'; +import { ChangeDetectorRef, Renderer2 } from '@angular/core'; import { Subject } from 'rxjs'; import { GridsterEmptyCell } from './gridsterEmptyCell.service'; import { GridsterCompact } from './gridsterCompact.service'; @@ -63,7 +63,6 @@ export abstract class GridsterComponentInterface { dragInProgress: boolean; emptyCell: GridsterEmptyCell; compact: GridsterCompact; - zone: NgZone; gridRows: Array; gridColumns: Array; } diff --git a/projects/angular-gridster2/src/lib/gridsterDraggable.service.ts b/projects/angular-gridster2/src/lib/gridsterDraggable.service.ts index e3afd569..e41fa17d 100644 --- a/projects/angular-gridster2/src/lib/gridsterDraggable.service.ts +++ b/projects/angular-gridster2/src/lib/gridsterDraggable.service.ts @@ -1,4 +1,4 @@ -import { NgZone } from '@angular/core'; +import { ChangeDetectorRef } from '@angular/core'; import { GridsterComponentInterface } from './gridster.interface'; import { DirTypes } from './gridsterConfig.interface'; import { GridsterItemComponentInterface } from './gridsterItem.interface'; @@ -20,6 +20,7 @@ enum Direction { export class GridsterDraggable { gridsterItem: GridsterItemComponentInterface; gridster: GridsterComponentInterface; + cdRef: ChangeDetectorRef; lastMouse: { clientX: number; clientY: number; @@ -61,10 +62,11 @@ export class GridsterDraggable { constructor( gridsterItem: GridsterItemComponentInterface, gridster: GridsterComponentInterface, - private zone: NgZone + cdRef: ChangeDetectorRef ) { this.gridsterItem = gridsterItem; this.gridster = gridster; + this.cdRef = cdRef; this.lastMouse = { clientX: 0, clientY: 0 @@ -102,18 +104,16 @@ export class GridsterDraggable { e.stopPropagation(); e.preventDefault(); - this.zone.runOutsideAngular(() => { - this.mousemove = this.gridsterItem.renderer.listen( - 'document', - 'mousemove', - this.dragMove - ); - this.touchmove = this.gridster.renderer.listen( - this.gridster.el, - 'touchmove', - this.dragMove - ); - }); + this.mousemove = this.gridsterItem.renderer.listen( + 'document', + 'mousemove', + this.dragMove + ); + this.touchmove = this.gridster.renderer.listen( + this.gridster.el, + 'touchmove', + this.dragMove + ); this.mouseup = this.gridsterItem.renderer.listen( 'document', 'mouseup', @@ -231,7 +231,7 @@ export class GridsterDraggable { if ( directions.includes(Direction.DOWN) && this.gridsterItem.el.getBoundingClientRect().bottom > - this.gridster.el.getBoundingClientRect().bottom - + this.gridster.el.getBoundingClientRect().bottom - (this.outerMarginBottom ?? this.margin) ) { directions = directions.filter( @@ -273,9 +273,7 @@ export class GridsterDraggable { this.calculateItemPosition(); this.lastMouse.clientX = e.clientX; this.lastMouse.clientY = e.clientY; - this.zone.run(() => { - this.gridster.updateGrid(); - }); + this.gridster.updateGrid(); }; calculateItemPositionWithScale(e: MouseEvent, scale: number): void { @@ -346,6 +344,7 @@ export class GridsterDraggable { if (this.gridster) { this.gridster.movingItem = null; this.gridster.previewStyle(true); + this.cdRef.markForCheck(); } }); }; @@ -509,6 +508,7 @@ export class GridsterDraggable { const timeout = setTimeout(() => { this.dragStart(e); cancelDrag(); + this.cdRef.markForCheck(); }, this.gridster.$options.draggable.delayStart); const cancelMouse = this.gridsterItem.renderer.listen( 'document', diff --git a/projects/angular-gridster2/src/lib/gridsterEmptyCell.service.ts b/projects/angular-gridster2/src/lib/gridsterEmptyCell.service.ts index ca4665f8..97d08a2c 100644 --- a/projects/angular-gridster2/src/lib/gridsterEmptyCell.service.ts +++ b/projects/angular-gridster2/src/lib/gridsterEmptyCell.service.ts @@ -84,13 +84,11 @@ export class GridsterEmptyCell { 'drop', this.emptyCellDragDrop ); - this.gridster.zone.runOutsideAngular(() => { - this.removeEmptyCellDragoverListenerFn = this.gridster.renderer.listen( - this.gridster.el, - 'dragover', - this.emptyCellDragOver - ); - }); + this.removeEmptyCellDragoverListenerFn = this.gridster.renderer.listen( + this.gridster.el, + 'dragover', + this.emptyCellDragOver + ); this.removeDocumentDragendListenerFn = this.gridster.renderer.listen( 'document', 'dragend', @@ -224,18 +222,16 @@ export class GridsterEmptyCell { this.initialItem = item; this.gridster.movingItem = item; this.gridster.previewStyle(); - this.gridster.zone.runOutsideAngular(() => { - this.removeWindowMousemoveListenerFn = this.gridster.renderer.listen( - 'window', - 'mousemove', - this.emptyCellMouseMove - ); - this.removeWindowTouchmoveListenerFn = this.gridster.renderer.listen( - 'window', - 'touchmove', - this.emptyCellMouseMove - ); - }); + this.removeWindowMousemoveListenerFn = this.gridster.renderer.listen( + 'window', + 'mousemove', + this.emptyCellMouseMove + ); + this.removeWindowTouchmoveListenerFn = this.gridster.renderer.listen( + 'window', + 'touchmove', + this.emptyCellMouseMove + ); this.removeWindowMouseupListenerFn = this.gridster.renderer.listen( 'window', 'mouseup', diff --git a/projects/angular-gridster2/src/lib/gridsterItem.component.ts b/projects/angular-gridster2/src/lib/gridsterItem.component.ts index b78b46ee..bf7ab0fb 100644 --- a/projects/angular-gridster2/src/lib/gridsterItem.component.ts +++ b/projects/angular-gridster2/src/lib/gridsterItem.component.ts @@ -1,11 +1,11 @@ import { + ChangeDetectorRef, Component, ElementRef, EventEmitter, HostBinding, Inject, Input, - NgZone, OnChanges, OnDestroy, OnInit, @@ -68,7 +68,7 @@ export class GridsterItemComponent @Inject(ElementRef) el: ElementRef, gridster: GridsterComponent, @Inject(Renderer2) public renderer: Renderer2, - @Inject(NgZone) private zone: NgZone + @Inject(ChangeDetectorRef) public cdRef: ChangeDetectorRef ) { this.el = el.nativeElement; this.$item = { @@ -78,8 +78,8 @@ export class GridsterItemComponent y: -1 }; this.gridster = gridster; - this.drag = new GridsterDraggable(this, gridster, this.zone); - this.resize = new GridsterResizable(this, gridster, this.zone); + this.drag = new GridsterDraggable(this, gridster, this.cdRef); + this.resize = new GridsterResizable(this, gridster); } ngOnInit(): void { diff --git a/projects/angular-gridster2/src/lib/gridsterResizable.service.ts b/projects/angular-gridster2/src/lib/gridsterResizable.service.ts index 1a27b68d..f54ac150 100644 --- a/projects/angular-gridster2/src/lib/gridsterResizable.service.ts +++ b/projects/angular-gridster2/src/lib/gridsterResizable.service.ts @@ -1,4 +1,3 @@ -import { NgZone } from '@angular/core'; import { GridsterComponentInterface } from './gridster.interface'; import { DirTypes } from './gridsterConfig.interface'; import { GridsterItemComponentInterface } from './gridsterItem.interface'; @@ -73,8 +72,7 @@ export class GridsterResizable { constructor( gridsterItem: GridsterItemComponentInterface, - gridster: GridsterComponentInterface, - private zone: NgZone + gridster: GridsterComponentInterface ) { this.gridsterItem = gridsterItem; this.gridster = gridster; @@ -113,18 +111,16 @@ export class GridsterResizable { e.stopPropagation(); e.preventDefault(); - this.zone.runOutsideAngular(() => { - this.mousemove = this.gridsterItem.renderer.listen( - 'document', - 'mousemove', - this.dragMove - ); - this.touchmove = this.gridster.renderer.listen( - this.gridster.el, - 'touchmove', - this.dragMove - ); - }); + this.mousemove = this.gridsterItem.renderer.listen( + 'document', + 'mousemove', + this.dragMove + ); + this.touchmove = this.gridster.renderer.listen( + this.gridster.el, + 'touchmove', + this.dragMove + ); this.mouseup = this.gridsterItem.renderer.listen( 'document', 'mouseup', @@ -294,9 +290,7 @@ export class GridsterResizable { this.lastMouse.clientX = e.clientX; this.lastMouse.clientY = e.clientY; - this.zone.run(() => { - this.gridster.updateGrid(); - }); + this.gridster.updateGrid(); }; dragStop = (e: MouseEvent): void => { @@ -476,10 +470,7 @@ export class GridsterResizable { if (this.gridster.options.enableBoundaryControl) { const margin = this.outerMarginBottom ?? this.margin; const box = this.gridster.el.getBoundingClientRect(); - this.bottom = Math.min( - this.bottom, - box.bottom - box.top - 2 * margin - ); + this.bottom = Math.min(this.bottom, box.bottom - box.top - 2 * margin); this.height = this.bottom - this.top; } const marginBottom = this.gridster.options.pushItems ? 0 : this.margin; @@ -603,58 +594,36 @@ export class GridsterResizable { cancelDrag(); }, this.gridster.$options.resizable.delayStart); - const { - cancelMouse, - cancelMouseLeave, - cancelOnBlur, - cancelTouchMove, - cancelTouchEnd, - cancelTouchCancel - } = this.zone.runOutsideAngular(() => { - // Note: all of these events are being added within the `` zone since they all - // don't do any view updates and don't require Angular running change detection. - // All event listeners call `cancelDrag` once the event is dispatched, the `cancelDrag` - // is responsible only for removing event listeners. - - const cancelMouse = this.gridsterItem.renderer.listen( - 'document', - 'mouseup', - cancelDrag - ); - const cancelMouseLeave = this.gridsterItem.renderer.listen( - 'document', - 'mouseleave', - cancelDrag - ); - const cancelOnBlur = this.gridsterItem.renderer.listen( - 'window', - 'blur', - cancelDrag - ); - const cancelTouchMove = this.gridsterItem.renderer.listen( - 'document', - 'touchmove', - cancelMove - ); - const cancelTouchEnd = this.gridsterItem.renderer.listen( - 'document', - 'touchend', - cancelDrag - ); - const cancelTouchCancel = this.gridsterItem.renderer.listen( - 'document', - 'touchcancel', - cancelDrag - ); - return { - cancelMouse, - cancelMouseLeave, - cancelOnBlur, - cancelTouchMove, - cancelTouchEnd, - cancelTouchCancel - }; - }); + const cancelMouse = this.gridsterItem.renderer.listen( + 'document', + 'mouseup', + cancelDrag + ); + const cancelMouseLeave = this.gridsterItem.renderer.listen( + 'document', + 'mouseleave', + cancelDrag + ); + const cancelOnBlur = this.gridsterItem.renderer.listen( + 'window', + 'blur', + cancelDrag + ); + const cancelTouchMove = this.gridsterItem.renderer.listen( + 'document', + 'touchmove', + cancelMove + ); + const cancelTouchEnd = this.gridsterItem.renderer.listen( + 'document', + 'touchend', + cancelDrag + ); + const cancelTouchCancel = this.gridsterItem.renderer.listen( + 'document', + 'touchcancel', + cancelDrag + ); function cancelMove(eventMove: MouseEvent): void { GridsterUtils.checkTouchEvent(eventMove); diff --git a/src/app/app.config.ts b/src/app/app.config.ts index c1b93d32..97bc52b9 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -2,9 +2,8 @@ import { HttpClient, provideHttpClient } from '@angular/common/http'; import { ApplicationConfig, importProvidersFrom, - provideZoneChangeDetection + provideExperimentalZonelessChangeDetection } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; import { provideRouter } from '@angular/router'; import { MarkdownModule, MARKED_OPTIONS } from 'ngx-markdown'; @@ -12,7 +11,7 @@ import { appRoutes } from './app.routes'; export const appConfig: ApplicationConfig = { providers: [ - provideZoneChangeDetection({ eventCoalescing: true }), + provideExperimentalZonelessChangeDetection(), provideRouter(appRoutes), provideHttpClient(), provideAnimationsAsync(),