0

I have a (login) component that gets state passed with the route. As far as I know, passed state can be read via Router.router.getCurrentNavigation()?.extras.state in the constructor and via history.state in other code, like in ngOnInit. This works if the component is being instatiated for the current route.

However I have a case where the component is not being instatiated for a new route because an instance already exists.

My question is how the component can get informed about changes in the state passed with the new route. I could not find any event I could use (like with ActivatedRoute.paramMap.subscribe(...) for route parameters). I found that history.state does not store my own state in routing events, hence events could not be used for my problem.

My use case is: A route is guarded by a authentication route card, passed to canResolve in the route definition. The route guard navigates to /login if the user is not authenticated. The return URL should be passed via state (not via a parameter). If the user klicks on one links for a guarded route (in the navigation bar), the login component gets the return URL from the state. If the user then clicks on another guarded link, the login component does not get the updated return URL.

I know that using a route parameter would solve my problem, but this is not the point. I generally want to know if a component can react to changes in passed route state.

Jürgen Bayer
  • 2,993
  • 3
  • 26
  • 51
  • How are you passing the state? What would be an example of a route with state you’d like to know about? – MikeOne Jan 09 '21 at 15:42
  • I am passing the state when routing in code: export class AuthGuard implements CanActivate { constructor(private authService: AuthService, private router: Router) { } canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { if (this.authService.isAuthenticated) { return true; } else { this.router.navigate(['/login'], { state: { returnUrl: state.url } } } } The route with state would be /login. – Jürgen Bayer Jan 09 '21 at 16:16

1 Answers1

0

One option, you maybe able to implement a custom/your own like here Subscribe/Fire on navigation/route events in app.component and firing AuthGuard, then save the state and access it as needed or save old routes

constructor(
  private router: Router,
  private route: ActivatedRoute,
  private authGuard: AuthGuard,
) {}

ngOnInit() {
  this.router.events
    .subscribe(event => {
      if (event instanceof RoutesRecognized) {
        this.guardRoute(event);
      }
    }));
}

private guardRoute(event: RoutesRecognized): void {
  if (this.isPublic(event)) {
    return;
  }

  if (!this.callCanActivate(event, this.authGuard)) {
    return;
  }
}
   
private callCanActivate(event: RoutesRecognized, guard: CanActivate) {
 
  return guard.canActivate(this.route.snapshot, event.state);
}

private isPublic(event: RoutesRecognized) {
  return event.state.root.firstChild.data.isPublic;
}
Transformer
  • 6,963
  • 2
  • 26
  • 52