Angularで前のページのURLを確認する方法は?


99

現在、URLのあるページを表示しているとします/user/:id。このページから次のページに移動します:id/posts

今の方法は、私はすなわち、前回のURLが何であるかを確認することができそうという、あります/user/:id

以下は私のルートです

export const routes: Routes = [
  { 
    path: 'user/:id', component: UserProfileComponent
  },
  {  
    path: ':id/posts', component: UserPostsComponet 
  }
];

回答:


80

ルート変更をサブスクライブして現在のイベントを保存し、次のイベントが発生したときに使用できるようにすることができます

previousUrl: string;
constructor(router: Router) {
  router.events
  .pipe(filter(event => event instanceof NavigationEnd))
  .subscribe((event: NavigationEnd) => {
    console.log('prev:', event.url);
    this.previousUrl = event.url;
  });
}

Angularでルート変更を検出する方法も参照してください


12
ありがとう@Günterあなたはいつも私の日を救います。
チャンドラシェカール2016

28
これは私にとって以前のルートをリストするのではなく、現在のルートだけをリストします。
David Aguirre 2017

2
あなたが期待するものに依存します。初めてnullは以前のルートがないからです。ルートルーターでもこれを行う必要があります。そうしないと、このコンポーネントの子ルート間を移動したときにのみ取得できます。
ギュンターZöchbauer

8
これは、コンストラクターが初めて実行されるときに以前のURLを提供しません。
Ekaitz Hernandez Troyas 2017

9
コンストラクターを初めて実行するときに、以前のURLとしてどのような値を期待しますか?
ギュンターZöchbauer

108

たぶん、他のすべての答えは角度2.Xに対するものです。

現在、Angular5.Xでは機能しません。私はそれを使っています。

NavigationEndのみでは、以前のURLを取得できません。

ルーターは「NavigationStart」、「RoutesRecognized」、...から「NavigationEnd」まで機能するためです。

で確認できます

    router.events.forEach((event) => {
  console.log(event);
});

ただし、「NavigationStart」を使用しても以前のURLを取得することはできません。

次に、ペアワイズを使用する必要があります。

import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/pairwise';

constructor(private router: Router) {
  this.router.events
    .filter(e => e instanceof RoutesRecognized)
    .pairwise()
    .subscribe((event: any[]) => {
      console.log(event[0].urlAfterRedirects);
    });
}
    

ペアワイズを使用すると、URLの送信元と送信先を確認できます。

「RoutesRecognized」は、起点からターゲットURLへの変更ステップです。

だからそれをフィルタリングし、それから前のURLを取得します。

最後だが大事なことは、

このコードを親コンポーネント以上(例:app.component.ts)に配置します

このコードはルーティングの終了後に起動するためです。

角度6+を更新

events.filterフィルタはイベントの一部ではないため、はエラーになります。コードを次のように変更してください。

import { filter, pairwise } from 'rxjs/operators';

this.router.events
.pipe(filter((evt: any) => evt instanceof RoutesRecognized), pairwise())
.subscribe((events: RoutesRecognized[]) => {
  console.log('previous url', events[0].urlAfterRedirects);
  console.log('current url', events[1].urlAfterRedirects);
});

2
サービスとして実装され、それは素晴らしい働きをします。私はAngular6.1.7を使用しています。
A. El Idrissi 2018年

5
@ tjvg1991ページを更新すると、メモリデータが失われます。以前のデータを保持する場合は、localStorageまたはcookieを使用する必要があります。(メモリではなくローカルにデータを保存する)
BYUNGJUJIN19年

賛成ボタンを殺したいだけですありがとうございます。
Muhammad Umair

@BYUNGJUJINありがとうございます!
ジョン

@ BYUNGJUJINありがとうございます。リダイレクトリンクからparamの値を取得するにはどうすればよいですか?たとえば、events [0] .urlAfterRedirectsは '/ InventoryDe​​tails; test = 0; id = 45'を取得しますが、これからidの値を取得したいと思います。subStringを使用せずに行うにはどうすればよいですか。
JNPW

49

注射可能なサービスを作成します。

import { Injectable } from '@angular/core';
import { Router, RouterEvent, NavigationEnd } from '@angular/router';

 /** A router wrapper, adding extra functions. */
@Injectable()
export class RouterExtService {

  private previousUrl: string = undefined;
  private currentUrl: string = undefined;

  constructor(private router : Router) {
    this.currentUrl = this.router.url;
    router.events.subscribe(event => {
      if (event instanceof NavigationEnd) {        
        this.previousUrl = this.currentUrl;
        this.currentUrl = event.url;
      };
    });
  }

  public getPreviousUrl(){
    return this.previousUrl;
  }    
}

次に、必要な場所で使用します。現在の変数をできるだけ早く保存するには、AppModuleでサービスを使用する必要があります。

// AppModule
export class AppModule {
  constructor(private routerExtService: RouterExtService){}

  //...

}

// Using in SomeComponent
export class SomeComponent implements OnInit {

  constructor(private routerExtService: RouterExtService, private location: Location) { } 

  public back(): void {
    this.location.back();
  }

  //Strange name, but it makes sense. Behind the scenes, we are pushing to history the previous url
  public goToPrevious(): void {
    let previous = this.routerExtService.getPreviousUrl();

    if(previous)
      this.routerExtService.router.navigateByUrl(previous);
  }

  //...

}

2
これが最もエレガントなソリューションだと思います。このコードを次の新しいフィルターとペアワイズソリューションとマージしてみてください:stackoverflow.com/a/35287471/518879
危険89 2018

2
追伸 そのように、(私の場合)アプリを-routing.module.tsにこのRouterExtServiceを追加することを忘れないでください:@NgModule({ ..., providers: [RouterExtService]}) export class AppRoutingModule { }
danger89

OK、このサービスソリューションには大きな問題があります。私の場合routerExtService.getPreviousUrl()、コンポーネントで使用されるサービスのコンストラクターでメソッドを呼び出します。何らかの理由で、これは実際の更新よりも早く呼び出されました。つまり、タイミングに依存しています。Subjectの方がはるかに使いやすいと思います。
危険8918

まあ、それは小さなプロジェクトで私にとってはうまくいきました。多分それはあなたのニーズに合うようにいくつかの微調整が必​​要です。問題を解決しましたか?
ジュリアーノ2018年

現在、いわゆるURLマトリックスパラメータを使用して、自分の状態をURLに「保存」しています。デフォルトでは、ブラウザのURLは、戻るボタンを使用したときに状態を保存します。let params = new HttpParams({fromString: retrieveURL}).set('name', 'victor') const paramsObject = params.keys().reduce((obj, key) => { obj[key] = params.get(key) return obj }, {}) this.router.navigate([paramsObject], { relativeTo: this.route })
危険8918年

20

以前のURLを文字列として取得するためのAngular6の更新されたコード。

import { Router, RoutesRecognized } from '@angular/router';
import { filter, pairwise } from 'rxjs/operators';


export class AppComponent implements OnInit {

    constructor (
        public router: Router
    ) {
    }

    ngOnInit() {
        this.router.events
            .pipe(filter((e: any) => e instanceof RoutesRecognized),
                pairwise()
            ).subscribe((e: any) => {
                console.log(e[0].urlAfterRedirects); // previous url
            });
    }

これにより、ガードによってブロックされたURLが返されますが、アクティブ化された(ガードによってブロックされていない)前のURLのみを取得する方法はありますか?
exocomp 2018

1
監視可能なルーターから退会するための最良の方法に関するヒントはありますか?
j4v1

動作します!「NavigationEnd」は動作しませんなぜ私は本当に知らない
davidwillianx

13

これは、Angular> = 6.xバージョンで機能しました:

this.router.events
            .subscribe((event) => {
              if (event instanceof NavigationStart) {
                window.localStorage.setItem('previousUrl', this.router.url);
              }
            });

11

2019バージョンのAngular8&rxjs 6

他の素晴らしいソリューションに基づいたソリューションを共有したいと思います。

まず、ルートの変更をリッスンするサービスを作成し、最後の前のルートをBehavior Subjectに保存します。次に、コンストラクターのメインapp.componentでこのサービスを提供し、このサービスを使用して、必要なときに必要な前のルートを取得します。

ユースケース:ユーザーを広告ページにリダイレクトしてから、ユーザーの元の場所に自動リダイレクトするため、最後の前のルートが必要です。

// service : route-events.service.ts

import { Injectable } from '@angular/core';
import { Router, RoutesRecognized } from '@angular/router';
import { BehaviorSubject } from 'rxjs';
import { filter, pairwise } from 'rxjs/operators';
import { Location } from '@angular/common';

@Injectable()
export class RouteEventsService {

    // save the previous route
  public previousRoutePath = new BehaviorSubject<string>('');

  constructor(
    private router: Router,
    private location: Location
  ) {

    // ..initial prvious route will be the current path for now
    this.previousRoutePath.next(this.location.path());


    // on every route change take the two events of two routes changed(using pairwise)
    // and save the old one in a behavious subject to access it in another component
    // we can use if another component like intro-advertise need the previous route
    // because he need to redirect the user to where he did came from.
    this.router.events.pipe(
      filter(e => e instanceof RoutesRecognized),
      pairwise(),
        )
    .subscribe((event: any[]) => {
        this.previousRoutePath.next(event[0].urlAfterRedirects);
    });

  }
}

app.moduleでサービスを提供します

  providers: [
    ....
    RouteEventsService,
    ....
  ]

app.componentに挿入します

  constructor(
    private routeEventsService: RouteEventsService
  )

最後に、保存した前のルートを必要なコンポーネントで使用します

  onSkipHandler(){
    // navigate the user to where he did came from
    this.router.navigate([this.routeEventsService.previousRoutePath.value]);
  }

これは本当にうまくいきます。しかし、私は簡単な質問があります。退会したことはありますか?
w0ns88

このようにtake(1)を追加します-> pairwise()、take(1))。subscribe((e:any)
Mukus

1
@Injectable({ providedIn: 'root' })サービスを使用する場合、サービスはプロジェクトのルートモジュール(AppModule)に自動的に読み込まれるため、手動でに提供する必要はありませんapp.module。詳細については、ドキュメントを参照してください。この回答に
Hkidd

10

Angular8を使用していますしていますが、@ franklin-piousの回答で問題が解決します。私の場合、サブスクライブ内の前のURLを取得すると、ビュー内のデータに添付されている場合にいくつかの副作用が発生します。

私が使用した回避策は、ルートナビゲーションのオプションパラメータとして前のURLを送信することでした。

this.router.navigate(['/my-previous-route', {previousUrl: 'my-current-route'}])

そして、コンポーネントでこの値を取得するには:

this.route.snapshot.paramMap.get('previousUrl')

this.routerとthis.routeは、各コンポーネントのコンストラクター内に挿入され、@ angular / routerメンバーとしてインポートされます。

import { Router, ActivatedRoute }   from '@angular/router';

5

ANGULAR7 +の場合

実際、Angular 7.2以降、以前のURLを保存するためのサービスを使用する必要はありません。ログインページにリンクする前に、stateオブジェクトを使用して最後のURLを設定することができます。ログインシナリオの例を次に示します。

@Component({ ... })
class SomePageComponent {
  constructor(private router: Router) {}

  checkLogin() {
    if (!this.auth.loggedIn()) {
      this.router.navigate(['login'], { state: { redirect: this.router.url } });
    }
  }
}
@Component({...})
class LoginComponent {
  constructor(private router: Router) {}

  backToPreviousPage() {
    const { redirect } = window.history.state;

    this.router.navigateByUrl(redirect || '/homepage');
  }
}
--------------------------------

さらに、テンプレートでデータを渡すこともできます。

@Component({
  template: '<a routerLink="/some-route" [state]="{ redirect: router.url}">Go to some route</a>'
})
class SomePageComponent {
  constructor(public router: Router) {}
}

3

@GünterZöchbauerもローカルストレージに保存できますが、私はそれを好みません)サービスに保存してそこからこの値を取得する方が良いです

 constructor(
        private router: Router
      ) {
        this.router.events
          .subscribe((event) => {
            if (event instanceof NavigationEnd) {
              localStorage.setItem('previousUrl', event.url);
            }
          });
      }

3

ここで説明されているように、ロケーションを使用できます。

リンクが新しいタブで開いた場合の私のコードは次のとおりです

navBack() {
    let cur_path = this.location.path();
    this.location.back();
    if (cur_path === this.location.path())
     this.router.navigate(['/default-route']);    
  }

必要な輸入品

import { Router } from '@angular/router';
import { Location } from '@angular/common';

1

previousNavigationオブジェクトを使用することで非常に簡単です:

this.router.events
  .pipe(
    filter(e => e instanceof NavigationEnd && this.router.getCurrentNavigation().previousNavigation),
    map(() => this.router.getCurrentNavigation().previousNavigation.finalUrl.toString()),
  )
  .subscribe(previousUrl => {}); 

1

ガード内の前のURLにアクセスするのに苦労しました。
カスタムソリューションを実装せずに、これは私のために働いています。

public constructor(private readonly router: Router) {
};

public ngOnInit() {
   this.router.getCurrentNavigation().previousNavigation.initialUrl.toString();
}

最初のURLは前のURLページになります。


-2

上記のすべての回答は、URLを複数回ロードします。ユーザーが他のコンポーネントにもアクセスした場合、これらのコードが読み込まれます。

とても使いやすい、サービス作成の概念。https://community.wia.io/d/22-access-the-previous-route-in-your-angular-5-app

これは、Angularのすべてのバージョンでうまく機能します。(app.moduleファイルのproviders配列に必ず追加してください!)


-2

rxjxのペアワイズを使用すると、これを簡単に実現できます。import {filter、pairwise} from'rxjs / operator ';

previousUrl: string;
constructor(router: Router) {
router.events
  .pipe(filter((evt: any) => evt instanceof RoutesRecognized), pairwise())
  .subscribe((events: RoutesRecognized[]) => {
  console.log('previous url', events[0].urlAfterRedirects);
  console.log('current url', events[1].urlAfterRedirects);
  this.previousUrl = events[0].urlAfterRedirects;
});

}


-6

前のページに戻りたいと思ったときも同様の問題がありました。解決策は想像以上に簡単でした。

<button [routerLink]="['../']">
   Back
</button>

そして、それは親URLに戻ります。私はそれが誰かを助けることを願っています;)


これは機能しません。OPが述べた以前のURLではなく、ルーターのパスを上に移動するように指示しています。
フレデリックYesid・ペーニャ・サンチェス

URLがパラメータと複雑な場合、または親と同じパスを持たない場合、これは機能しません。「何か/親/子」から「何か/親」に戻りたい場合にのみ機能します。
A. El Idrissi 2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.