docs(router): Update router guide to use UrlTree for guard redirects (#37100)

The current implementation for redirecting users inside guards was in place
before the feature was added to allow `CanActivate` and `CanActivateChild` guards
to return `UrlTree` for redirecting users.

Returning `UrlTree` should be the default method, as it provides a more desirable
redirecting experience. When using `router.navigate` followed by `return false`,
the `Router` calls `resetUrlToCurrentUrlTree` (in the `finalize` operator) before
processing the navigation to the new route.  This can result in an undesirable
history if the navigation was the first navigation in the application - that is,
the route will briefly be reset to just `/` (see #36187).

Fixes #36187

PR Close #37100
This commit is contained in:
Andrew Scott
2020-05-13 14:13:43 -07:00
committed by Kara Erickson
parent 77c0ef38be
commit 8a56c99f87
4 changed files with 22 additions and 23 deletions

View File

@ -1,6 +1,6 @@
// #docregion
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, UrlTree } from '@angular/router';
import { AuthService } from './auth.service';
@ -12,21 +12,20 @@ export class AuthGuard implements CanActivate {
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
state: RouterStateSnapshot): true|UrlTree {
let url: string = state.url;
return this.checkLogin(url);
}
checkLogin(url: string): boolean {
checkLogin(url: string): true|UrlTree {
if (this.authService.isLoggedIn) { return true; }
// Store the attempted URL for redirecting
this.authService.redirectUrl = url;
// Navigate to the login page with extras
this.router.navigate(['/login']);
return false;
// Redirect to the login page
return this.router.parseUrl('/login');
}
}
// #enddocregion

View File

@ -4,7 +4,8 @@ import {
CanActivate, Router,
ActivatedRouteSnapshot,
RouterStateSnapshot,
CanActivateChild
CanActivateChild,
UrlTree
} from '@angular/router';
import { AuthService } from './auth.service';
@ -16,7 +17,7 @@ export class AuthGuard implements CanActivate, CanActivateChild {
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
state: RouterStateSnapshot): true|UrlTree {
let url: string = state.url;
return this.checkLogin(url);
@ -24,20 +25,19 @@ export class AuthGuard implements CanActivate, CanActivateChild {
canActivateChild(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
state: RouterStateSnapshot): true|UrlTree {
return this.canActivate(route, state);
}
// #enddocregion can-activate-child
checkLogin(url: string): boolean {
checkLogin(url: string): true|UrlTree {
if (this.authService.isLoggedIn) { return true; }
// Store the attempted URL for redirecting
this.authService.redirectUrl = url;
// Navigate to the login page
this.router.navigate(['/login']);
return false;
// Redirect to the login page
return this.router.parseUrl('/login');
}
// #docregion can-activate-child
}

View File

@ -6,7 +6,8 @@ import {
ActivatedRouteSnapshot,
RouterStateSnapshot,
CanActivateChild,
NavigationExtras
NavigationExtras,
UrlTree
} from '@angular/router';
import { AuthService } from './auth.service';
@ -16,17 +17,17 @@ import { AuthService } from './auth.service';
export class AuthGuard implements CanActivate, CanActivateChild {
constructor(private authService: AuthService, private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): true|UrlTree {
let url: string = state.url;
return this.checkLogin(url);
}
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): true|UrlTree {
return this.canActivate(route, state);
}
checkLogin(url: string): boolean {
checkLogin(url: string): true|UrlTree {
if (this.authService.isLoggedIn) { return true; }
// Store the attempted URL for redirecting
@ -42,8 +43,7 @@ export class AuthGuard implements CanActivate, CanActivateChild {
fragment: 'anchor'
};
// Navigate to the login page with extras
this.router.navigate(['/login'], navigationExtras);
return false;
// Redirect to the login page with extras
return this.router.createUrlTree(['/login'], navigationExtras);
}
}