From 2e868f24fe4dc0f23473105c6ff1c14c2d0b8fe0 Mon Sep 17 00:00:00 2001 From: sanderelias Date: Thu, 29 May 2025 10:06:07 +0200 Subject: [PATCH 1/6] fix: user afterrender and host --- .../src/lib/split/split.component.ts | 35 ++++++++----------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/projects/angular-split/src/lib/split/split.component.ts b/projects/angular-split/src/lib/split/split.component.ts index dae82e4..cffd395 100644 --- a/projects/angular-split/src/lib/split/split.component.ts +++ b/projects/angular-split/src/lib/split/split.component.ts @@ -1,3 +1,4 @@ +import { DOCUMENT, NgStyle, NgTemplateOutlet } from '@angular/common' import { ChangeDetectionStrategy, Component, @@ -5,12 +6,11 @@ import { HostBinding, InjectionToken, NgZone, - Renderer2, + afterRenderEffect, booleanAttribute, computed, contentChild, contentChildren, - effect, inject, input, isDevMode, @@ -18,7 +18,6 @@ import { signal, } from '@angular/core' import { takeUntilDestroyed } from '@angular/core/rxjs-interop' -import type { SplitAreaComponent } from '../split-area/split-area.component' import { Subject, filter, @@ -33,26 +32,26 @@ import { takeUntil, tap, } from 'rxjs' +import { ANGULAR_SPLIT_DEFAULT_OPTIONS } from '../angular-split-config.token' +import { SplitGutterDynamicInjectorDirective } from '../gutter/split-gutter-dynamic-injector.directive' +import { SplitGutterDirective } from '../gutter/split-gutter.directive' +import { SplitAreaSize, SplitGutterInteractionEvent } from '../models' +import type { SplitAreaComponent } from '../split-area/split-area.component' +import { SplitCustomEventsBehaviorDirective } from '../split-custom-events-behavior.directive' import { ClientPoint, + assertUnreachable, createClassesString, - gutterEventsEqualWithDelta, fromMouseMoveEvent, fromMouseUpEvent, getPointFromEvent, + gutterEventsEqualWithDelta, leaveNgZone, numberAttributeWithFallback, sum, toRecord, - assertUnreachable, } from '../utils' -import { DOCUMENT, NgStyle, NgTemplateOutlet } from '@angular/common' -import { SplitGutterInteractionEvent, SplitAreaSize } from '../models' -import { SplitCustomEventsBehaviorDirective } from '../split-custom-events-behavior.directive' import { areAreasValid } from '../validations' -import { SplitGutterDirective } from '../gutter/split-gutter.directive' -import { SplitGutterDynamicInjectorDirective } from '../gutter/split-gutter-dynamic-injector.directive' -import { ANGULAR_SPLIT_DEFAULT_OPTIONS } from '../angular-split-config.token' interface MouseDownContext { mouseDownEvent: MouseEvent | TouchEvent @@ -85,10 +84,12 @@ export const SPLIT_AREA_CONTRACT = new InjectionToken('Split templateUrl: './split.component.html', styleUrl: './split.component.css', changeDetection: ChangeDetectionStrategy.OnPush, + host: { + '[style.gridTemplate]': 'gridTemplateColumnsStyle()', + }, }) export class SplitComponent { private readonly document = inject(DOCUMENT) - private readonly renderer = inject(Renderer2) private readonly elementRef = inject>(ElementRef) private readonly ngZone = inject(NgZone) private readonly defaultOptions = inject(ANGULAR_SPLIT_DEFAULT_OPTIONS) @@ -164,7 +165,7 @@ export class SplitComponent { constructor() { if (isDevMode()) { // Logs warnings to console when the provided areas sizes are invalid - effect(() => { + afterRenderEffect(() => { // Special mode when no size input was declared which is a valid mode if (this.unit() === 'percent' && this._visibleAreas().every((area) => area.size() === 'auto')) { return @@ -174,14 +175,6 @@ export class SplitComponent { }) } - // Responsible for updating grid template style. Must be this way and not based on HostBinding - // as change detection for host binding is bound to the parent component and this style - // is updated on every mouse move. Doing it this way will prevent change detection cycles in parent. - effect(() => { - const gridTemplateColumnsStyle = this.gridTemplateColumnsStyle() - this.renderer.setStyle(this.elementRef.nativeElement, 'grid-template', gridTemplateColumnsStyle) - }) - this.gutterMouseDownSubject .pipe( filter( From 529fa50481f018a445e813e6977456f9a72fa7c2 Mon Sep 17 00:00:00 2001 From: sanderelias Date: Thu, 29 May 2025 15:23:02 +0200 Subject: [PATCH 2/6] fix: use read phase --- .../angular-split/src/lib/split/split.component.ts | 14 ++++++++------ .../split-transitions.component.ts | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/projects/angular-split/src/lib/split/split.component.ts b/projects/angular-split/src/lib/split/split.component.ts index cffd395..2fb808a 100644 --- a/projects/angular-split/src/lib/split/split.component.ts +++ b/projects/angular-split/src/lib/split/split.component.ts @@ -165,13 +165,15 @@ export class SplitComponent { constructor() { if (isDevMode()) { // Logs warnings to console when the provided areas sizes are invalid - afterRenderEffect(() => { - // Special mode when no size input was declared which is a valid mode - if (this.unit() === 'percent' && this._visibleAreas().every((area) => area.size() === 'auto')) { - return - } + afterRenderEffect({ + read: () => { + // Special mode when no size input was declared which is a valid mode + if (this.unit() === 'percent' && this._visibleAreas().every((area) => area.size() === 'auto')) { + return + } - areAreasValid(this._visibleAreas(), this.unit(), true) + areAreasValid(this._visibleAreas(), this.unit(), true) + }, }) } diff --git a/src/app/examples/split-transitions/split-transitions.component.ts b/src/app/examples/split-transitions/split-transitions.component.ts index b71c4c8..763bc25 100644 --- a/src/app/examples/split-transitions/split-transitions.component.ts +++ b/src/app/examples/split-transitions/split-transitions.component.ts @@ -267,7 +267,7 @@ export class SplitTransitionsComponent extends AComponent { setTimeout(() => { const logsEl = this.logsEl() if (logsEl.nativeElement.scroll) { - ;(logsEl.nativeElement).scroll({ top: this.logMessages.length * 30 }) + (logsEl.nativeElement).scroll({ top: this.logMessages.length * 30 }) } }) } From 534c06540c36f98b55c132435bb8c3e863c4d714 Mon Sep 17 00:00:00 2001 From: sanderelias Date: Fri, 30 May 2025 08:51:22 +0200 Subject: [PATCH 3/6] fix: prevent excessive CD --- .../angular-split/src/lib/split/split.component.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/projects/angular-split/src/lib/split/split.component.ts b/projects/angular-split/src/lib/split/split.component.ts index 2fb808a..b55d085 100644 --- a/projects/angular-split/src/lib/split/split.component.ts +++ b/projects/angular-split/src/lib/split/split.component.ts @@ -84,9 +84,9 @@ export const SPLIT_AREA_CONTRACT = new InjectionToken('Split templateUrl: './split.component.html', styleUrl: './split.component.css', changeDetection: ChangeDetectionStrategy.OnPush, - host: { - '[style.gridTemplate]': 'gridTemplateColumnsStyle()', - }, + // host: { + // '[style.gridTemplate]': 'gridTemplateColumnsStyle()', + // }, }) export class SplitComponent { private readonly document = inject(DOCUMENT) @@ -177,6 +177,13 @@ export class SplitComponent { }) } + afterRenderEffect({ + read: () => { + const gridTemplate = this.gridTemplateColumnsStyle() + this.elementRef.nativeElement.style.gridTemplate = gridTemplate + }, + }) + this.gutterMouseDownSubject .pipe( filter( From b91b98929e9b9658a38a7c15693b09ae2a485b53 Mon Sep 17 00:00:00 2001 From: sanderelias Date: Fri, 30 May 2025 09:01:47 +0200 Subject: [PATCH 4/6] fix: add explainatory comment --- projects/angular-split/src/lib/split/split.component.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/projects/angular-split/src/lib/split/split.component.ts b/projects/angular-split/src/lib/split/split.component.ts index b55d085..9feee04 100644 --- a/projects/angular-split/src/lib/split/split.component.ts +++ b/projects/angular-split/src/lib/split/split.component.ts @@ -177,10 +177,12 @@ export class SplitComponent { }) } + // we are running this after Angular has completed its CD loop + // as we are updating the style of the host, and we don't want to re-trigger the CD loop + // doing this in the host of the component would retrigger the CD too many times afterRenderEffect({ read: () => { - const gridTemplate = this.gridTemplateColumnsStyle() - this.elementRef.nativeElement.style.gridTemplate = gridTemplate + this.elementRef.nativeElement.style.gridTemplate = this.gridTemplateColumnsStyle() }, }) From 9b24e55b1d039d932bf5f3101612ac6c2aea755c Mon Sep 17 00:00:00 2001 From: sanderelias Date: Fri, 30 May 2025 10:01:43 +0200 Subject: [PATCH 5/6] fix: add explainatory comment, and move to write phase --- projects/angular-split/src/lib/split/split.component.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/projects/angular-split/src/lib/split/split.component.ts b/projects/angular-split/src/lib/split/split.component.ts index 9feee04..6e19201 100644 --- a/projects/angular-split/src/lib/split/split.component.ts +++ b/projects/angular-split/src/lib/split/split.component.ts @@ -166,6 +166,9 @@ export class SplitComponent { if (isDevMode()) { // Logs warnings to console when the provided areas sizes are invalid afterRenderEffect({ + // we use the afterRender read phase here, + // because we want to run this after all processing is done. + // and we are not updating anything in the DOM read: () => { // Special mode when no size input was declared which is a valid mode if (this.unit() === 'percent' && this._visibleAreas().every((area) => area.size() === 'auto')) { @@ -181,7 +184,7 @@ export class SplitComponent { // as we are updating the style of the host, and we don't want to re-trigger the CD loop // doing this in the host of the component would retrigger the CD too many times afterRenderEffect({ - read: () => { + write: () => { this.elementRef.nativeElement.style.gridTemplate = this.gridTemplateColumnsStyle() }, }) From 6b4418bf5947b84d45f18ecff9d14bacffb53cdd Mon Sep 17 00:00:00 2001 From: sanderelias Date: Fri, 30 May 2025 10:02:53 +0200 Subject: [PATCH 6/6] fix: remove stale comment --- projects/angular-split/src/lib/split/split.component.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/projects/angular-split/src/lib/split/split.component.ts b/projects/angular-split/src/lib/split/split.component.ts index 6e19201..5e639a9 100644 --- a/projects/angular-split/src/lib/split/split.component.ts +++ b/projects/angular-split/src/lib/split/split.component.ts @@ -84,9 +84,6 @@ export const SPLIT_AREA_CONTRACT = new InjectionToken('Split templateUrl: './split.component.html', styleUrl: './split.component.css', changeDetection: ChangeDetectionStrategy.OnPush, - // host: { - // '[style.gridTemplate]': 'gridTemplateColumnsStyle()', - // }, }) export class SplitComponent { private readonly document = inject(DOCUMENT)