Angular Routerメモ

(Angular v.4.3.6を利用)

参考

リンクを設定したい

通常

<a routerLink="/path">link</a>

<!-- relative routerLink -->
<a routerLink="./path">link</a>

パラメータがついたリンク

<!-- route param (/path/1) -->
<a [routerLink]="['/path', 1 ]">link</a>

<!-- matrix param (/path;matrixParam=value) -->
<a [routerLink]="['/path', { matrixParam: 'value' } ]">link</a>

<!-- query param (/path?page=1) -->
<a [routerLink]="['/path']" [queryParams]="{ page: 1 }">link</a>

アンカー(#)がついたリンク

<!-- fragment (/path#anchor) -->
<a [routerLink]="['/path']" fragment="anchor">link</a>

アクティブなリンクにクラスを設定したい

  • routerLinkActiveを利用
<a routerLink="/path" routerLinkActive="active">link</a>

<a routerLink="/path" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">link</a>

<a routerLink="/path" [routerLinkActive]="['active', 'border']">link</a>

ts内で遷移の制御をしたい

通常

this.router.navigate(['/path']);

// relative link
this.router.navigate(['path'], { relativeTo: this.route });

パラメータをつける

// route param (/path/1)
this.router.navigate(['path', '1'], { relativeTo: this.route });

// matrix param (/path;matrixParam=value)
this.router.navigate(['/path',  { matrixParam: 'value' }]);

// query param (/path?page=1)
this.router.navigate(['/path'], { queryParams: { page: 1 } });

アンカー(#)をつける

// fragment (/path#anchor)
this.router.navigate(['/path'], { fragment: 'anchor' });

クエリを保存して遷移したい

参考

コンポーネント内でパラメータを取得したい

Observableで取得

constructor(private route: ActivatedRoute) {}

ngOnInit() {
  /**
   * Routeの設定が { path: 'view/:id' }
   * URLが /view/10;matrixParam=value?page=1 の場合
   */
  this.route.paramMap
    .subscribe((params: ParamMap) => {
      // params.keys.forEach(key => {

        const routeParam = params.get('id');
        // -> 10

        const matrixParam = params.get('matrixParam');
        // -> value
      // });
    });

  this.route.queryParamMap
    .subscribe((params: ParamMap) => {
      const queryParam = this.route.snapshot.queryParamMap.get('page');
      // -> 1
    });
}

route.snapshotから取得

constructor(private route: ActivatedRoute) {}

// ...

/**
 * Routeの設定が { path: 'view/:id' }
 * URLが /view/10;matrixParam=value?page=1 の場合
 */
const routeParam = this.route.snapshot.paramMap.get('id');
// -> 10

const matrixParam = this.route.snapshot.paramMap.get('matrixParam');
// -> value

const queryParam = this.route.snapshot.queryParamMap.get('page');
// -> 1

特定のRouteに紐付けないパラメータを利用したい

  • クエリパラメータを利用
    • https://angular.io/guide/router#query-parameters-and-fragments
      • In the route parameters example, you only dealt with parameters specific to the route, but what if you wanted optional parameters available to all routes? This is where query parameters come into play.

        ルートパラメータの例では、ルートに固有のパラメータのみを扱いますが、オプションのパラメータをすべてのルートで使用できるようにしたい場合はどうなりますか?ここでクエリパラメータが有効になります。

前回のURLを取得したい

アプリ初期時に処理を追加したい

  • (Routerとは直接関係ないけど)
  • APP_INITIALIZERを利用
  • 設定ファイルのロードや権限確認などに利用できそう
@NgModule({
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: (sites:SitesService) => () => sites.load(),
      deps: [SitesService],
      multi: true,
    }
  ]
})
export class AppModule { }
@Injectable()
export class SitesService {
  constructor() { }
  load(): Promise<any> {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        // doing something
        // ...

        resolve();
      }, 3000);
    });
  }
}

参考

Routerのナビゲーションイベントを確認したい

constructor(private router: Router) {

    // 遷移開始時のイベントを確認
    router.events.subscribe(event => {
      if (event instanceof NavigationStart) {
        console.log(event);

        // リダイレクトさせることも(一応)可能
        // if (event.url !== '/view-a') {
        //   router.navigate(['view-b']);
        // }
      }
    });
  }

その他

  • イベントのログをコンソールで確認(デバッグ用)
    • RouterModule.forRoot(appRoutes, { enableTracing: true })

コンポーネントの再利用について知りたい

  • routeConfigが同じならコンポーネントは再利用される
    • パラメータが変わっても再描画はされない
// https://github.com/angular/angular/blob/54e02449549448ebab6f255f2da0b4396665c6f0/packages/router/src/route_reuse_strategy.ts#L66
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
  return future.routeConfig === curr.routeConfig;
}

カスタマイズしたい

参考

RouterとActivatedRouteについて知りたい

その他

複数のRouteを表示したい

<router-outlet></router-outlet>

<!--popupという名前のoutletを設定 -->
<router-outlet name="popup"></router-outlet>

<!-- `path: 'compose'`に紐づけられているコンポーネントを表示 -->
<a [routerLink]="[{ outlets: { popup: ['compose'] } }]">Contact</a>
// `path: 'compose'`に紐づけられているコンポーネントを表示
this.router.navigate([{ outlets: { popup: 'compose' } }]);

// null でクリアできる
this.router.navigate([{ outlets: { popup: null }}]);

「遷移前に認証チェックをしたい」「遷移前に未保存のデータがあるか確認をしたい」など

遷移前にデータを読み込みたい

遅延読み込み

基本設定

読み込み開始前にガードしたい

プリロードさせたい

RouterModule.forRoot(
  appRoutes,
  {
    // PreloadAllModules
    //   https://angular.io/api/router/PreloadAllModules
    //   guardされていないrouteが全てプリロードされる
    preloadingStrategy: PreloadAllModules
  }
)
@Injectable()
export class CustomPreloadingStrategy implements PreloadingStrategy {
  preload(route: Route, load: () => Observable<any>): Observable<any> {

    // routeの設定情報に `data: { preload: true }` があればプリロードする
    if (route.data && route.data['preload']) {
      return load();
    } else {
      return Observable.of(null);
    }
  }
}