2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Angular】現在開いているページのURLを取得したい

Last updated at Posted at 2022-02-25

やりたいこと

  • 現在開いているページの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'.

・・・???:thinking:

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しているんですね。
スクリーンショット 2022-02-26 7.58.06.png

URLを取得する場合の問題点(2022.2.27追記)

  • 現在開いているページのURLを取得したい
  • URLに応じてCSSの切り替えや変数の生成を行いたい

という用途には不適切なのでは?と思ったのは、該当routerconstructor内に記術したやつ)のRouterEventが起きずに画面が表示される場合に対応できないため。

例えば

  • 画面をリロードした場合
  • 検索バーに直接URLを打ち込んで遷移してきた場合
  • 親のrouterから遷移してきた場合

上のような場合は該当routerRouterEventが起きず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();
  }
}
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?