Skip to content

Reconcile Angular Router with platform routing

Your app routes internally with the Angular Router; the shell owns the top-level URL. Keep them in sync in both directions:

  • App → shell: report your in-app subpath with platform.route.report so the shell can deep-link to it and restore it. Default pushes a back-able history entry; pass { replace: true } for filter/tab changes you do not want in history.
  • Shell → app: subscribe with platform.route.onShellNavigate so that when the shell drives navigation (browser back/forward, a deep link), your router follows.
routed-app.ts
import { Component, OnDestroy, inject } from "@angular/core";
import { NavigationEnd, Router } from "@angular/router";
import type { Subscription } from "rxjs";
import { filter } from "rxjs/operators";
import { PLATFORM } from "../shared/platform.token";
// Reconciling the Angular Router with platform routing. Two directions:
// app → shell: report the in-app route so the shell can deep-link and restore it (replace:false
// pushes a back-able entry; replace:true is for filters/tabs).
// shell → app: when the shell drives navigation (back/forward, a deep link), follow it.
@Component({
selector: "routed-app",
template: `<router-outlet></router-outlet>`,
})
export class RoutedApp implements OnDestroy {
private readonly platform = inject(PLATFORM);
private readonly router = inject(Router);
private readonly sub: Subscription;
private readonly offShellNav: () => void;
constructor() {
this.sub = this.router.events
.pipe(filter((e): e is NavigationEnd => e instanceof NavigationEnd))
.subscribe((e) => this.platform.route.report(e.urlAfterRedirects, { replace: false }));
this.offShellNav = this.platform.route.onShellNavigate((subpath) => {
void this.router.navigateByUrl(subpath);
});
}
ngOnDestroy(): void {
this.sub.unsubscribe();
this.offShellNav();
}
}