66 * found in the LICENSE file at https://angular.dev/license
77 */
88
9- import { AfterRenderPhase , AfterRenderRef } from './api' ;
10- import { NgZone } from '../../zone' ;
11- import { inject } from '../../di/injector_compatibility' ;
12- import { ɵɵdefineInjectable } from '../../di/interface/defs' ;
13- import { ErrorHandler } from '../../error_handler' ;
9+ import { TracingAction , TracingService , TracingSnapshot } from '../../application/tracing' ;
1410import {
1511 ChangeDetectionScheduler ,
1612 NotificationSource ,
1713} from '../../change_detection/scheduling/zoneless_scheduling' ;
14+ import { inject } from '../../di/injector_compatibility' ;
15+ import { ɵɵdefineInjectable } from '../../di/interface/defs' ;
16+ import { ErrorHandler } from '../../error_handler' ;
1817import { type DestroyRef } from '../../linker/destroy_ref' ;
19- import { TracingAction , TracingService , TracingSnapshot } from '../../application/tracing' ;
18+ import { NgZone } from '../../zone' ;
19+ import { AFTER_RENDER_SEQUENCES_TO_ADD , FLAGS , LView , LViewFlags } from '../interfaces/view' ;
20+ import { markAncestorsForTraversal } from '../util/view_utils' ;
21+ import { AfterRenderPhase , AfterRenderRef } from './api' ;
2022
2123export class AfterRenderManager {
2224 impl : AfterRenderImpl | null = null ;
@@ -102,22 +104,34 @@ export class AfterRenderImpl {
102104 this . sequences . add ( sequence ) ;
103105 }
104106 if ( this . deferredRegistrations . size > 0 ) {
105- this . scheduler . notify ( NotificationSource . DeferredRenderHook ) ;
107+ this . scheduler . notify ( NotificationSource . RenderHook ) ;
106108 }
107109 this . deferredRegistrations . clear ( ) ;
108110 }
109111
110112 register ( sequence : AfterRenderSequence ) : void {
111- if ( ! this . executing ) {
112- this . sequences . add ( sequence ) ;
113- // Trigger an `ApplicationRef.tick()` if one is not already pending/running, because we have a
114- // new render hook that needs to run.
115- this . scheduler . notify ( NotificationSource . RenderHook ) ;
113+ const { view} = sequence ;
114+ if ( view !== undefined ) {
115+ // Delay adding it to the manager, add it to the view instead.
116+ ( view [ AFTER_RENDER_SEQUENCES_TO_ADD ] ??= [ ] ) . push ( sequence ) ;
117+
118+ // Mark the view for traversal to ensure we eventually schedule the afterNextRender.
119+ markAncestorsForTraversal ( view ) ;
120+ view [ FLAGS ] |= LViewFlags . HasChildViewsToRefresh ;
121+ } else if ( ! this . executing ) {
122+ this . addSequence ( sequence ) ;
116123 } else {
117124 this . deferredRegistrations . add ( sequence ) ;
118125 }
119126 }
120127
128+ addSequence ( sequence : AfterRenderSequence ) : void {
129+ this . sequences . add ( sequence ) ;
130+ // Trigger an `ApplicationRef.tick()` if one is not already pending/running, because we have a
131+ // new render hook that needs to run.
132+ this . scheduler . notify ( NotificationSource . RenderHook ) ;
133+ }
134+
121135 unregister ( sequence : AfterRenderSequence ) : void {
122136 if ( this . executing && this . sequences . has ( sequence ) ) {
123137 // We can't remove an `AfterRenderSequence` in the middle of iteration.
@@ -172,6 +186,7 @@ export class AfterRenderSequence implements AfterRenderRef {
172186 constructor (
173187 readonly impl : AfterRenderImpl ,
174188 readonly hooks : AfterRenderHooks ,
189+ readonly view : LView | undefined ,
175190 public once : boolean ,
176191 destroyRef : DestroyRef | null ,
177192 public snapshot : TracingSnapshot | null = null ,
@@ -194,5 +209,9 @@ export class AfterRenderSequence implements AfterRenderRef {
194209 destroy ( ) : void {
195210 this . impl . unregister ( this ) ;
196211 this . unregisterOnDestroy ?.( ) ;
212+ const scheduled = this . view ?. [ AFTER_RENDER_SEQUENCES_TO_ADD ] ;
213+ if ( scheduled ) {
214+ this . view [ AFTER_RENDER_SEQUENCES_TO_ADD ] = scheduled . filter ( ( s ) => s !== this ) ;
215+ }
197216 }
198217}
0 commit comments