Skip to content

Commit d45982c

Browse files
andershessellundAnders Hessellund Jensen
andauthored
Modal: Prevent router subscription during Angular teardown (#4582)
Co-authored-by: Anders Hessellund Jensen <bdyah2@bankdata.dk>
1 parent 598a036 commit d45982c

1 file changed

Lines changed: 13 additions & 4 deletions

File tree

libs/designsystem/modal/src/modal-navigation.service.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ import {
66
Params,
77
Route,
88
Router,
9+
Event as RouterEvent,
910
Routes,
1011
} from '@angular/router';
11-
import { EMPTY, firstValueFrom, Observable } from 'rxjs';
12+
import { defer, EMPTY, firstValueFrom, Observable, Subject } from 'rxjs';
1213
import { filter, map, pairwise, skipUntil, startWith, takeUntil } from 'rxjs/operators';
1314

1415
import { ModalRouteActivation } from './modal.interfaces';
@@ -20,6 +21,14 @@ export class ModalNavigationService {
2021
private route: ActivatedRoute
2122
) {}
2223

24+
// Angular Router unsubscribes its internal events Subject during dispose() (e.g. on TestBed teardown).
25+
// Subscribing to a closed Subject throws ObjectUnsubscribedError, so route all subscriptions through
26+
// this defer-wrapped stream that falls back to EMPTY when the underlying Subject is already closed.
27+
private routerEvents$: Observable<RouterEvent> = defer(() => {
28+
const events = this.router.events;
29+
return (events as Subject<RouterEvent>).closed ? EMPTY : events;
30+
});
31+
2332
isModalRoute(url: string): boolean {
2433
return url.includes('(modal:');
2534
}
@@ -204,7 +213,7 @@ export class ModalNavigationService {
204213
return previousModalRouteParent !== currentModalRouteParent;
205214
}
206215

207-
private navigationEndListener$ = this.router.events.pipe(
216+
private navigationEndListener$ = this.routerEvents$.pipe(
208217
filter((event): event is NavigationEnd => event instanceof NavigationEnd)
209218
);
210219

@@ -351,13 +360,13 @@ export class ModalNavigationService {
351360
}
352361

353362
handleBrowserBackButton(modal: HTMLIonModalElement) {
354-
const popstateNavigationStart$ = this.router.events.pipe(
363+
const popstateNavigationStart$ = this.routerEvents$.pipe(
355364
filter(
356365
(event): event is NavigationStart =>
357366
event instanceof NavigationStart && event.navigationTrigger === 'popstate'
358367
)
359368
);
360-
const navigationEnd$ = this.router.events.pipe(
369+
const navigationEnd$ = this.routerEvents$.pipe(
361370
filter((event) => event instanceof NavigationEnd)
362371
);
363372
navigationEnd$

0 commit comments

Comments
 (0)