やりたいこと
現在開いているページのURLを取得したいURLに応じてCSSの切り替えや変数の生成を行いたい- (同一router内での)画面遷移後に何かしらのイベントを行いたい
(2022.2.27 追記)これらの用途には不適切な場合もあるなーーと思い1.2個目削除。理由は一番下に記載しました。
方法
公式ドキュメントにある通り、router.events
からRouterEvent
をsubscribeします。
import { NavigationEnd, RouterEvent, Router } from '@angular/router';
class MyService {
constructor(private router: Router) {
this.router.events.pipe(
filter((e: Event): e is RouterEvent => e instanceof RouterEvent)
).subscribe((e: RouterEvent) => {
// Do something
});
}
}
すると、コンパイルエラー発生。
Error: app.component.ts:25:9 - error TS2345: Argument of type 'MonoTypeOperatorFunction' is not assignable to parameter of type 'OperatorFunction'.
・・・???
DOMのEventとrouterのEventは別物だよ!だから@angular/router
からEventをインポートしてちょ!とのこと。
import { Event,<--追加 NavigationEnd, RouterEvent, Router } from '@angular/router';
class MyService {
constructor(private router: Router) {
this.router.events.pipe(
filter((e: Event): e is RouterEvent => e instanceof NavigationEnd)
).subscribe((e: RouterEvent) => {
// Do something
});
}
}
よくみると公式のドキュメントのコードでもちゃんとimport { Event, RouterEvent, Router } from '@angular/router';
と記述あります。
filter((e: Event): e is RouterEvent => e instanceof RouterEvent)
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
見慣れないこの辺に気を取られてました。
is
とかinstanceof
に関してはこの辺が分かりやすそうです。記事書けるほど理解できてないので参考URLだけ。
- 戻り値の型アノテーション
is
instanceof
ちなみに
import { Router } from '@angular/router';
class MyService {
constructor(private router: Router) {
router.events.subscribe(e => {
console.log(e)
});
}
}
のようにするとズラーっとeventが出てくるので、必要なNavigationEnd
だけfilterしているんですね。
URLを取得する場合の問題点(2022.2.27追記)
- 現在開いているページのURLを取得したい
- URLに応じてCSSの切り替えや変数の生成を行いたい
という用途には不適切なのでは?と思ったのは、該当router
(constructor
内に記術したやつ)のRouterEvent
が起きずに画面が表示される場合に対応できないため。
例えば
- 画面をリロードした場合
- 検索バーに直接URLを打ち込んで遷移してきた場合
- 親のrouterから遷移してきた場合
上のような場合は該当router
のRouterEvent
が起きずURLを取得できない。(この説明で合ってるのかは正直分かりません・・・)
ただし、上のような場合においては
this.router.url
でURLを取得できます。(ただし、RouterEvent
は検知できない)
なので併用が良いんじゃないかなあと。僕の今のコードはこんな感じになっております。
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Event, NavigationEnd, Router, RouterEvent } from '@angular/router';
// Rxjs
import { Subject } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
styleUrls: ['./example.component.scss'],
})
export class ExampleComponent implements OnInit, OnDestroy {
private onDestroy$ = new Subject();
currentUrl:string = '';
constructor(
private router: Router
) { }
ngOnInit(): void {
this.currentUrl = this.router.url;
this.router.events
.pipe(
takeUntil(this.onDestroy$),
filter((event: Event): event is RouterEvent => event instanceof NavigationEnd),
).subscribe((event: RouterEvent) => {
this.currentUrl = event.url;
});
}
ngOnDestroy(): void {
this.onDestroy$.next();
}
}