この記事は何?
Angular 7.1 から Guard の 返り値として UrlTree が指定できるようになりました。
このアップデートにより、Guard 内の記述が直感的になったので紹介したいと思います。
現在の最新版は 7.1.0-beta.2
ですが、自分が試す限りは不具合等なく快適に使用できるので時間がある方は是非リファクタしてみてください ( ´ ▽ ` )
Before
サンプルコードは、ほとんどのアプリで使われていそうなログイン状態確認用 Guard にしたいと思います。
/mypage
的なパスへ設定して、ログインしていない場合はログインページへ遷移させる典型的なパターンで使います。
canActivate
の返り値は Observable<boolean> | Promise<boolean> | boolean
ですが、記述が冗長で読みづらいため使っている型のみ指定しています。
@Injectable()
export class AuthGUard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
public canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
): boolean {
if (this.authService.isSignIn()) {
// 認証後専用ページへ遷移
return true;
}
// ログインページへ遷移
this.router.navigate(['auth/sign-in']);
// ルーティング中止
return false;
}
}
なんというか、ルーティングの流れを一旦止めてるのに別軸で新たな流れを生み出して無理やり遷移している感じがちょっと気持ち悪いなぁと感じていました。
After
@Injectable()
export class AuthGUard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
public canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
): boolean | UrlTree {
if (this.authService.isSignIn()) {
// 認証後専用ページへ遷移
return true;
}
- // ログインページへ遷移
- this.router.navigate(['auth/sign-in']);
-
- // ルーティング中止
- return false;
+ // 現在のルーティングを中止し、ログインページへ遷移
+ return this.router.parseUrl('auth/sign-in');
}
}
これぞ求めていたもの!って感じです。
非常に明快なコードになりました。
もちろん Observable
や Promise
型でも OK なので、場合によって使い分けてください。
export interface CanActivate {
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree;
}
おまけ
skipLocationChange
等のオプションを指定している場合は createUrlTree
をご利用ください。
(というか、使う or 使わない の判断しなくて良いので全部こっちでいいかも、、、
return this.router.createUrlTree(['auth', 'sign-in'], {
skipLocationChange: true,
queryParams: {
[ReturnUrlParamName]: state.url,
},
});