web-dev-qa-db-ja.com

Angular 2つの新しいルーター:子コンポーネントのルーターパラメーターを取得する方法は?

@angular/router3.0.0-rc.1の最新バージョンでは、URL /ルートからパラメーターを取得する方法が変更されました。

this ドキュメンテーションに基づいて、paramsにサブスクライブすることでparamsを取得できるはずですが、私の場合は機能していないようです。

私が達成したいのは、子ルートから親コンポーネントにパラメータを取得することです。

たとえば、これが私のルートだとしましょう:

const routes: Routes = [
  {
    path: 'parent',
    component: ParentComponent,
    pathMatch: 'prefix',
    children: [
      {
        path: ':id',
        component: ChildComponent
      }
    ]
  }
];

idパラメーターを取得して、ParentComponentで使用します。だから私はこのようにしようとしています:

export class ParentComponent implements OnInit {

  sub: any;
  constructor(
    private route: ActivatedRoute) {
    this.route = route;
   }

  ngOnInit() {

    this.sub = this.route.params.subscribe(params => {
     let id = params['id'];
     console.log(id);
   });

  }

}

このように私は得ています:

Undefined

ここに何が欠けていますか?

14
Vassilis Pits

ActivatedRouteには、その親/子ルート情報にアクセスするためのゲッターがあります。

親から最初の子ルートにアクセスするには、次を使用します。

this.route.firstChild.params

すべての子ルートが必要な場合は、childrenプロパティを使用します。 ActivatedRouteの配列を返します

this.route.children

子ルートにいて、親からのパラメーターが必要な場合:

this.route.parent.params

26
Brandon

子パラメーターは、子と関連付け/保管されます ActivatedRoute 。親のActivatedRouteでは使用できません。したがって、最初にゲッターfirstChildまたはchildrenを使用して子のActivatedRouteを取得する必要があります。

次に、親は子パラメーターの変更をサブスクライブできます。

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute }               from '@angular/router';
import { Subscription }                 from 'rxjs/Subscription';

export class ParentComponent implements OnInit, OnDestroy {
   private sub: Subscription;
   constructor(private route: ActivatedRoute) {}
   ngOnInit() {
      this.sub = this.route.firstChild.params.subscribe(
        params => console.log(params.id));
   }
   ngOnDestroy() {
      this.sub.unsubscribe();
   }
}

または、子パラメーターのスナップショットを取得できます。

import { Component }      from '@angular/core';
import { ActivatedRoute } from '@angular/router';

export class ParentComponent {
   constructor(private route: ActivatedRoute) {}
   someMethod() {
      console.log(this.route.firstChild.snapshot.params.id);
   }
}

すべての子を取得する場合(複数のアウトレットがある場合など)、ActivatedRoute.childrenまたはActivatedRouteSnapshot.childrenを使用して、子ActivatedRoutesまたは子ActivatedRouteShapshotsの配列を取得します。

5
Mark Rajcok

ActivatedRouteを使用して子パラメーターを取得するのは非常に簡単ですが、現在の子を変更すると、すぐに問題に遭遇する可能性があります。

最初にいくつかの注意事項:

  • activatedRoute.firstChildプロパティはActivatedRouteインスタンスであり、オブザーバブルではありません。
  • また、activatedRoute.paramMapは観察可能です。

問題に直面する方法は次のとおりです。

  • 一度に1つしか表示されない2つの子ルート(および対応するコンポーネント)を持つコンポーネント(タブ付きインターフェースなど)を考えてください。
  • ngOnInitハンドラー内でfirstChild.paramMapにアクセスすると、それにサブスクライブして、パラメーターの変化を監視できます。これは見た目も動作も問題ありません。
  • 2番目のタブに切り替えてから最初のタブに戻ると、すべてが壊れます。これは、すでに存在していないActivatedRouteインスタンスでparamMapを最初にサブスクライブしたためです。
  • 重要:これは、子供のparamMapにアクセスしようとしている場合にのみ問題になります。 「自分の」paramMapにアクセスしようとしている場合、または子コンポーネントもparamMapを挿入する場合、すべてが正常になります。

私が見つけたこれに対する最もクリーンなソリューションは次のとおりです。

注:最初にrouter: Routerに加えてroute: ActivatedRouteを注入します。

const firstChildParams$ = this.router.events.pipe(filter(e => e instanceof NavigationEnd),
                                                  startWith(undefined),
                                                  switchMap(e => this.route.firstChild!.paramMap));

これは、NavigationEndイベントのみをリッスンし、その後新しいfirstChildが利用可能になります。 switchMapを使用することで、古い冗長マップのサブスクライブ解除を心配する必要がなくなります。また、ナビゲーションイベントの実際の値が使用されることはなく、startWithが初めてパラメーターをすぐに処理できるようにするために必要であるというわけでもありません。

私はこのような便利なものをRouterHelperServiceに集めており、どこにでも注入でき、この狂気をすべて覚える必要はありません。


いつかfirstChildに相当するものがあるはずだと提案するかもしれませんが、これは問題にはなりません。ただし、他のシナリオではさらに混乱を招く可能性があります!

3
Simon_Weaver
this.route.snapshot.paramMap.get('id');
1
labu4bd

this.activatedRoute.snapshot.firstChild.paramsを使用して

1
gildniy
  this.router.events.subscribe(event => {
            if (event instanceof RoutesRecognized) {
                // let strId = event.state.root.firstChild.children[0].data;
                let a = event.state.root.firstChild.children.map((route) => {
                    while (route.firstChild) {
                        route = route.firstChild;
                    }

                    return route;
                });
                console.log('Title', a[0].data.title);
                this.meta.updateTitle(a[0].data.title);
            }
            if (event instanceof NavigationEnd) {
                (<any>window).gtag('config', this.googleAnalyticsCode, {
                    'page_title' : this.titleService.getTitle(),
                    'page_path': event.urlAfterRedirects
                });
            }
        });
0
atjoshi