Angular 2オプションのルートパラメーター


180

Angular 2ルートにオプションのルートパラメーターを含めることは可能ですか?RouteConfigでAngular 1.x構文を試しましたが、以下のエラーを受け取りました:

"元の例外:パス" / user /:id? "に"? "が含まれていますが、これはルート構成では許可されていません。"

@RouteConfig([
{
    path: '/user/:id?',
    component: User,
    as: 'User'
}])

回答:


298

パラメータの有無にかかわらず、複数のルートを定義できます。

@RouteConfig([
    { path: '/user/:id', component: User, name: 'User' },
    { path: '/user', component: User, name: 'Usernew' }
])

コンポーネントのオプションパラメータを処理します。

constructor(params: RouteParams) {
    var paramId = params.get("id");

    if (paramId) {
        ...
    }
}

関連するgithubの問題も参照してください:https : //github.com/angular/angular/issues/3525


11
私が間違っている場合は修正してください。ただし、この解決策は、配列内のルートの順序が逆になっている場合にのみ機能しました。私がそうするまで、ルーターはパラメーターなしのルートとのみ一致しました。
Aviad P.

10
このソリューションはまだ適用されますか?「User」から「UserNew」に移動すると、「User」コンポーネントが再びインスタンス化されることに気づきました
teleaziz

19
古いが、このアプローチの大きな問題は、各ルートが一意のルートとして扱われ、コンポーネントの再利用が不可能になることです。
苦悶

4
@teleazizで述べたように、パラメータを追加すると、コンポーネントが再レンダリングされます。これを回避するために、Martin Cremerの答え。空のパラメータ値に「redirectTo」ルートを追加して、私のために素晴らしい仕事:stackoverflow.com/a/49159166/1364650 -しかし、それは非常にハックですが、私は、彼らはちょうど適切にオプションのルートパラメータをサポートすべきだと思います。
Vincent Sels 2018

2
なぜRouteParamsコンポーネントにインポートしないのか不思議に思っている人のために、これをチェックしてください:stackoverflow.com/a/36792261/806202。解決策は、使用することですActivatedRouteroute.snapshot.params['routeParam']
アルセンKhachaturyan

89
{path: 'users', redirectTo: 'users/', pathMatch: 'full'},
{path: 'users/:userId', component: UserComponent}

この方法では、パラメーターが追加されたときにコンポーネントが再レンダリングされません。


6
この答えが一番です。同じコンポーネントを再レンダリングせず、複数のコンポーネントを必要としません。
Rex

4
最良の答えですがpathMatch: 'full'、リダイレクトに追加しました。それ以外の場合users/adminは、私の場合も同様にパスがリダイレクトされます
Valeriy Katkov

4
この回答は、ブラウザで表示したURLの末尾にスラッシュを付けても問題がない場合にのみ最適です。多分例えば、「未定義のID」を表す値を考えてみましょう/users/allか、/users/homeなど「すべて」または「ホーム」を読んで、idそれはあなたの魔法の値と一致した場合、単にそれを無視します。次に、上の最初の行はredirectTo: 'users/home'または決定したものになります。私にとって、末尾のスラッシュは何かが間違っているように本当に際立っています。
Simon_Weaver

@Simon_Weaver同意する。この問題のないマッチャーを使用した別の解決策を見つけました:stackoverflow.com/a/56391974/664533
Wayne Maurer

1
それは単純な呪文ですが、まったく壊れません:D最善の解決策!
Verri

45

情報がオプションの場合は、クエリパラメータを使用することをお勧めします。

ルートパラメータまたはクエリパラメータ?

厳格な規則はありません。一般に、

経路パラメータを優先する

  • 値は必須です。
  • この値は、あるルートパスを別のルートパスと区別するために必要です。

クエリパラメータを優先する

  • 値はオプションです。
  • 値は複雑または多変量です。

https://angular.io/guide/router#optional-route-parametersから

ルートパスからパラメーターを取り出すだけです。

@RouteConfig([
{
    path: '/user/',
    component: User,
    as: 'User'
}])

6
オプションのルートパラメータを変更するとコンポーネントが再レンダリングされますが、queryParamsを変更すると再レンダリングされません。また、ルートナビゲーションの前に一部のデータを解決すると、オプションのルートパラメータを変更するたびに要求されます。
Rakhat 16

1
参考までに、そのアンカーリンクはもう機能しません。新しいリンクはルートパラメータのようです:必須かオプションか?
spottedmahn

20

Angular 4-オプションのパラメーターの順序に対処するソリューション:

これを行う:

const appRoutes: Routes = [
  {path: '', component: HomeComponent},
  {path: 'products', component: ProductsComponent},
  {path: 'products/:id', component: ProductsComponent}
]

productsproducts/:idルートの名前はまったく同じであることに注意してください。Angular 4はproducts、パラメーターのないルートでも正しくフォローしますproducts/:id。パラメーターの場合は、フォローします。

ただし、非パラメータールートのパスには末尾にスラッシュがあってはproductsなりませ。そうでない場合、angularは誤ってそれをパラメーターパスとして扱います。したがって、私の場合、製品の末尾にスラッシュがあり、機能しませんでした。

これをしないでください:

...
{path: 'products/', component: ProductsComponent},
{path: 'products/:id', component: ProductsComponent},
...

両方がProductsComponentに送信される場合、そこでオプションのパラメーターをどのように処理しますか?
アーウィン

1
次のように、:id1、:id2などのパラメーターと、ProductsComponentで要求されたURLにアクセスできます:this.route.url.first().mergeMap((url)=> {// console.log( '1: url change detected '+ url); return this.route.params.do((params)=> {// console.log(' 2:url + params change detected '+ params ["id1"] +' '+ params ["id2"]); this.id1 = params ["id1"]; this.id2 = params ["id2"];})})
ObjectiveTC

2
dataコンポーネントに渡すこともできますが、同じコンポーネントでも、ルートごとに異なる可能性があります。例{path: 'products', component: ProductsComponent, data: { showAllProducts: true} },を使用してから、を確認しshowAllProductsます。nullをチェックするよりも少し良いですが、より単純なケースではおそらくどちらでも問題ありません。
Simon_Weaver 2018年

1
残念ながら、このソリューションでは、Angularが製品と製品/:IDの間でコンポーネントを再利用できなくなります。コンポーネントが再インスタンス化されます。
コディアック

@コディアック-私はそれが正しいとは思わない。私の理解では、app.module.tsでは、ProductsComponentが1回インスタンス化され、角度エンジンは、ナビゲート可能な各イベント(productsおよびproducts /:idなど)でそのインスタンス化されたProductsComponentを再利用します。上記のコードでProductsComponentがどのように再インスタンス化されるのか、またどのようにして再インスタンス化を防ぐのかについて説明またはデモできますか?
ObjectiveTC

11

rerezzの答えはかなりいいですが、重大な欠陥が1つあります。これにより、UserコンポーネントはngOnInitメソッドを再実行します。

重い作業をそこで行い、ノンパラメトリックルートからパラメトリックルートに切り替えるときに再実行したくない場合は、問題が発生する可能性があります。これらの2つのルートは、オプションのurlパラメータを模倣するためのものですが、2つの個別のルートになることはありません。

これは私が問題を解決するために提案するものです:

const routes = [
  {
    path: '/user',
    component: User,
    children: [
      { path: ':id', component: UserWithParam, name: 'Usernew' }
    ]
  }
];

次に、パラメーターの処理を担当するロジックをUserWithParamコンポーネントに移動し、基本ロジックをコンポーネントに残しUserます。/ userから/ user / 123にUser::ngOnInit移動しても、何を実行しても二度と実行されません。

置くことを忘れないでください<router-outlet></router-outlet>Userのテンプレート。


コンポーネントの再作成を回避することは、パフォーマンスが重要な場合に有効です。:私はまた避け、別の解決策は再作成コンポーネントビーイング回避していstackoverflow.com/a/56391974/664533
ウェイン・マウラー

4

複数のルートエントリを追加することを提案するrerezzからの承認済みの回答を含め、ここで推奨される回答は正常に機能します。

ただし、コンポーネントは、ルートエントリ間、つまりパラメータ付きのルートエントリとパラメータなしのエントリとの間で変更されたときに再作成されます。

これを避けたい場合は、両方のルートに一致する独自のルートマッチャーを作成できます。

export function userPageMatcher(segments: UrlSegment[]): UrlMatchResult {
    if (segments.length > 0 && segments[0].path === 'user') {
        if (segments.length === 1) {
            return {
                consumed: segments,
                posParams: {},
            };
        }
        if (segments.length === 2) {
            return {
                consumed: segments,
                posParams: { id: segments[1] },
            };
        }
        return <UrlMatchResult>(null as any);
    }
    return <UrlMatchResult>(null as any);
 }

次に、ルート構成でマッチャーを使用します。

const routes: Routes = [
    {
        matcher: userPageMatcher,
        component: User,
    }
];

@KevinBeal AOTで動作するマッチャーをかなり実装しました。ここで発生しているエラーは何ですか?
ウェイン

おっとっと。それは何か別のものでした。私のマッチャーはAOTで動作します。
Kevin Beal

これは少しトリッキーですが、この問題の最良の解決策
fedor.belov

4

angular4では、ルートを階層にまとめる必要があるだけです

const appRoutes: Routes = [
  { 
    path: '', 
    component: MainPageComponent 
  },
  { 
    path: 'car/details', 
    component: CarDetailsComponent 
  },
  { 
    path: 'car/details/platforms-products', 
    component: CarProductsComponent 
  },
  { 
    path: 'car/details/:id', 
    component: CadDetailsComponent 
  },
  { 
    path: 'car/details/:id/platforms-products', 
    component: CarProductsComponent 
  }
];

これは私にとってはうまくいきます。このようにして、ルータはオプションIDパラメータに基づいて次のルートを認識します。


1

この問題の別のインスタンスに遭遇し、その解決策を探す際にここに来ました。私の問題は、私が子供たちをやっていることと、コンポーネントの遅延読み込みも少し最適化することでした。つまり、親モジュールを遅延ロードする場合です。ルートで '/:id'を使用することが主なものでしたが、 '/'がその一部であるという不満があります。ここでは正確な問題ではありませんが、それは当てはまります。

親からのアプリルーティング

...
const routes: Routes = [
  {
    path: '',
    children: [
      {
        path: 'pathOne',
        loadChildren: 'app/views/$MODULE_PATH.module#PathOneModule'
      },
      {
        path: 'pathTwo',
        loadChildren: 'app/views/$MODULE_PATH.module#PathTwoModule'
      },
...

子ルートの遅延読み込み

...
const routes: Routes = [
  {
    path: '',
    children: [
      {
        path: '',
        component: OverviewComponent
      },
      {
        path: ':id',
        component: DetailedComponent
      },
    ]
  }
];
...


0

遅延読み込みで同様の問題に直面している私はこれを行いました:

const routes: Routes = [
  {
    path: 'users',
    redirectTo: 'users/',
    pathMatch: 'full'
  },
  {
    path: 'users',
    loadChildren: './users/users.module#UserssModule',
    runGuardsAndResolvers: 'always'
  },
[...]

そしてコンポーネントで:

  ngOnInit() {
    this.activatedRoute.paramMap.pipe(
      switchMap(
        (params: ParamMap) => {
          let id: string = params.get('id');
          if (id == "") {
            return of(undefined);
          }
          return this.usersService.getUser(Number(params.get('id')));
        }
      )
    ).subscribe(user => this.selectedUser = user);
  }

こちらです:

  • なしのルート/は、次のルートにリダイレクトされます。のため、そのpathMatch: 'full'ような特定の完全なルートのみがリダイレクトされます。

  • その後、users/:id受け取ります。実際のルートがだったusers/場合id""、それをチェックインし、それにngOnInit応じて行動します。それ以外の場合idはIDであり、続行します。

  • 残りのコンポーネントの動作selectedUserは未定義であるか、未定義ではありません(* ngIfなど)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.