From 0ecd9b96982e132e68b7cdd0fa89c78ba80fd4e4 Mon Sep 17 00:00:00 2001 From: sumeyye Date: Thu, 6 Aug 2026 15:57:25 +0300 Subject: [PATCH] fix: some bugs for the upgrade --- .../core/src/lib/directives/permission.directive.ts | 4 +++- .../components/breadcrumb/breadcrumb.component.html | 2 +- .../components/breadcrumb/breadcrumb.component.ts | 13 ++++++------- .../src/lib/services/toaster.service.ts | 6 +++--- .../src/lib/tests/breadcrumb.component.spec.ts | 2 +- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts index b12782288d..d9ad09c780 100644 --- a/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts +++ b/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts @@ -52,7 +52,9 @@ export class PermissionDirective implements OnDestroy, OnChanges, AfterViewInit if (!this.rendered) { this.cdrSubject.next(); } else { - this.cdRef.detectChanges(); + // Defer via queue — sync detectChanges during ApplicationRef.tick + // (e.g. post-login permission/config refresh) can contribute to NG0101. + this.queue.add(() => this.cdRef.detectChanges()); } } else { this.cdRef.markForCheck(); diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb/breadcrumb.component.html b/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb/breadcrumb.component.html index b23fdc598e..1eabd84821 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb/breadcrumb.component.html +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb/breadcrumb.component.html @@ -1 +1 @@ - + diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb/breadcrumb.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb/breadcrumb.component.ts index b8a86342b1..884eb9db99 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb/breadcrumb.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb/breadcrumb.component.ts @@ -6,7 +6,7 @@ import { SubscriptionService, TreeNode, } from '@abp/ng.core'; -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, OnInit, inject, signal } from '@angular/core'; import { Router } from '@angular/router'; import { map, startWith } from 'rxjs/operators'; import { eThemeSharedRouteNames } from '../../enums/route-names'; @@ -20,14 +20,13 @@ import { BreadcrumbItemsComponent } from '../breadcrumb-items/breadcrumb-items.c imports: [BreadcrumbItemsComponent], }) export class BreadcrumbComponent implements OnInit { - readonly cdRef = inject(ChangeDetectorRef); private router = inject(Router); private routes = inject(RoutesService); private subscription = inject(SubscriptionService); private routerEvents = inject(RouterEvents); private routeCultureUrl = inject(RouteBasedCultureUrlService); - segments: Partial[] = []; + readonly segments = signal[]>([]); ngOnInit(): void { this.subscription.addOne( @@ -38,18 +37,18 @@ export class BreadcrumbComponent implements OnInit { ), ), route => { - this.segments = []; + const next: Partial[] = []; if (route) { let node = { parent: route } as TreeNode; while (node.parent) { node = node.parent; const { parent, children, isLeaf, ...segment } = node; - if (!isAdministration(segment)) this.segments.unshift(segment); + if (!isAdministration(segment)) next.unshift(segment); } - - this.cdRef.detectChanges(); } + + this.segments.set(next); }, ); } diff --git a/npm/ng-packs/packages/theme-shared/src/lib/services/toaster.service.ts b/npm/ng-packs/packages/theme-shared/src/lib/services/toaster.service.ts index b6db6e7716..f1f3a5c114 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/services/toaster.service.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/services/toaster.service.ts @@ -1,4 +1,4 @@ -import { ApplicationRef, ComponentRef, inject, Injectable } from '@angular/core'; +import { ComponentRef, inject, Injectable } from '@angular/core'; import { ContentProjectionService, LocalizationParam, @@ -12,7 +12,6 @@ import { Toaster } from '../models'; providedIn: 'root', }) export class ToasterService implements ToasterContract { - private readonly appRef = inject(ApplicationRef); private readonly contentProjectionService = inject(ContentProjectionService); private lastId = -1; @@ -37,8 +36,9 @@ export class ToasterService implements ToasterContract { } this.containerComponentRef.instance.setToasts(this.toasts); + // Only refresh the projected toast host. Calling ApplicationRef.tick() here + // races with zone-driven CD and throws NG0101 (recursive tick). this.containerComponentRef.changeDetectorRef.detectChanges(); - this.appRef.tick(); } /** diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/breadcrumb.component.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/breadcrumb.component.spec.ts index 6ad217d3b8..ce1463e2cf 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/breadcrumb.component.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/breadcrumb.component.spec.ts @@ -135,7 +135,7 @@ describe('BreadcrumbComponent', () => { const breadcrumb = spectator.fixture.debugElement.query(By.directive(BreadcrumbComponent)) .componentInstance as BreadcrumbComponent; - expect(breadcrumb.segments.map(segment => segment.path)).toEqual([ + expect(breadcrumb.segments().map(segment => segment.path)).toEqual([ '/identity', '/identity/users', ]);