59

私は最新のAngular 2リリース候補に取り組んでいるアプリケーションをアップグレードしています。この作業の一環として、NgModule仕様を使用し、アプリケーションのすべての部分をモジュールに移行しようとしています。ほとんどの場合、これはルーティングに関する問題を除いて非常にうまくいっています。

"@angular/common": "2.0.0-rc.5",
"@angular/compiler": "2.0.0-rc.5",
"@angular/core": "2.0.0-rc.5",
"@angular/forms": "0.3.0",
"@angular/http": "2.0.0-rc.5",
"@angular/platform-browser": "2.0.0-rc.5",
"@angular/platform-browser-dynamic": "2.0.0-rc.5",
"@angular/router": "3.0.0-rc.1",

私のアプリはモジュールの構成として構築され、いくつかのモジュールが親モジュールの子として一緒に接着されています。たとえば、通知モジュール、ユーザーモジュール、およびTelphonyモジュール(たとえば)で構成される管理モジュールがあります。これらのモジュールへのルートは次のようになります。

/admin/notifications/my-notifications
/admin/users/new-user
/admin/telephony/whatever

ルータの以前のリリースでは、これは "子供"を使って簡単に達成できました

export const AdminRoutes: RouterConfig = [
   {
      path: "Admin",
      component: AdminComponent,
      Children: [
         ...UserRoutes,
         ...TelephonyRoutes,
         ...NotificationRoutes
      ]
   }
]

別のファイルでは、サブモジュールの一部として、個々のモジュールルートも同様に定義します。

export const UserRoutes: RouterConfig = [
    {
       path: "users",
       component: userComponent,
       children: [
           {path: "new-user", component: newUserComponent}
       ]
    }

]

これはすべてうまくいった。 Modulesにアップグレードする過程で、私はすべてを自分の個別のルーティングファイルに入れ替えました

const AdminRoutes: Routes = [
    {path: "admin", component: AdminComponent}
] 

export const adminRouting = RouterModule.forChild(AdminRoutes)

そして

const UserRoutes: Routes = [
       path: "users",
       component: userComponent,
       children: [
           {path: "new-user", component: newUserComponent}
       ]
] 

export const userRouting = RouterModule.forChild(UserRoutes)

そのすべてを整えて、私はuserRoutingをインポートするUsersModuleを持っていて、次にadminRoutesとUsersModuleをインポートするAdminModuleを持っています。私の考えは、UsersModuleはAdminModuleの子であるため、ルーティングは以前と同じように動作します。残念ながら、そうではありませんので、私はユーザールートで終わります

/users/new-user 

の代わりに

/admin/users/new-user

さらに、これにより、新しいユーザーコンポーネントは、自分のアプリケーションのスタイリングとナビゲーションをスローする管理コンポーネントのルーターアウトレットに読み込まれません。

私の人生のために、自分のUserModuleのルートをAdminModuleの子として参照する方法を考え出すことができません。私は古い方法でこれをやろうとしていて、ルートが2つのモジュールにあることについてのエラーを得る。明らかにこれは新しくリリースされているので、これらのケースのいくつかのドキュメントは少し限られています。

誰でも助けることができれば大いに感謝します!


7 답변


47

さて、週末のより良いところでこれを騒がした後、私はそれを私の最後に走らせました。最終的に私のために働いたのは次のことでした:

  • すべてエクスポートRoutesあなたがルーティングしたいすべてのモジュールのために。いずれかをインポートしないでくださいRouterModule.forChild()子モジュール内にある。
  • 輸出するすべてコンポーネントは、子モジュール定義の子ルート定義から可視です。
  • インポート(Typescriptを意味する)importキーワード)を使用して...オペレータはこれらを正しい経路の下に組み込むことができます。私はそれがパスを定義する子モジュールで動作するようにすることはできませんでしたが、親にそれを持たせることはうまく動作します(遅延ロードと互換性があります)。

私の場合、私はこのような階層に3つのレベルを持っていました:

  • ルート(/
    • 編集者 (editor/:projectId
      • クエリ(query/:queryId
      • ページ(page/:pageId
    • 前面 (about

次の定義は、/editor/:projectId/query/:queryIdパス:

// app.routes.ts
import {editorRoutes}                   from './editor/editor.routes'

// Relevant excerpt how to load those routes, notice that the "editor/:projectId"
// part is defined on the parent
{
    path: '',
    children: [
        {
            path: 'editor/:projectId',
            children: [...editorRoutes]
            //loadChildren: '/app/editor/editor.module'
        },
    ]
}

エディタルートは次のようになります。

// app/editor/editor.routes.ts
import {queryEditorRoutes}              from './query/query-editor.routes'
import {pageEditorRoutes}               from './page/page-editor.routes'

{
    path: "", // Path is defined in parent
    component : EditorComponent,
    children : [
        {
            path: 'query',
            children: [...queryEditorRoutes]
            //loadChildren: '/app/editor/query/query-editor.module'
        },
        {
            path: 'page',
            children: [...pageEditorRoutes]
            //loadChildren: '/app/editor/page/page-editor.module'
        }
    ]
}

そして、QueryEditorの最後の部分は次のようになります:

// app/editor/query/query-editor.routes.ts
{
    path: "",
    component : QueryEditorHostComponent,
    children : [
        { path: 'create', component : QueryCreateComponent },
        { path: ':queryId', component : QueryEditorComponent }
    ]
}

しかし、この作業を行うためには、一般Editor輸入する必要があるそして輸出するQueryEditorそしてそのQueryEditor輸出する必要があるQueryCreateComponentそしてQueryEditorComponentこれらはインポート時に表示されるためです。これをしないと、Component XYZ is defined in multiple modules

遅延ロードもこの設定でうまくいくことに注意してください。この場合、子ルートはもちろんインポートされるべきではありません。


  • これは有望に見えます、そして、私はあなたがそれに入れている時間を感謝します。あなたのモジュール定義を少し明確にすることができますか?ルーティングファイルから正確に何をエクスポートするのですか?あなたはRoutes []をエクスポートしていますか、またはルーティングファイルからRouterModule.forChild()をエクスポートしていますか?そして、それらをモジュールにエクスポート/インポートすることで、それらを表示することができますか?これまでの私の試みでは、RouterOutletが2回定義されているというエラーが発生し、モジュールのRoutes []をエクスポートしようとするとunexpect [オブジェクト、オブジェクト]がエクスポートされるという問題が発生しました。 - John Ackerman
  • ああ、申し訳ありません...私は何とかあなたのコメントを読んで、それに答えることはしませんでした。あなたは私がで終わった全体のセットアップを見ることができますbitbucket.org/marcusriemer/esqulino/src/… - Marcus Riemer
  • 私はこの答えを得るのに時間を費やしました。明確化と詳細な回答をありがとう。角度のある文書へのリンクを得る機会はありますか? - eagle.dan.1349
  • 私はこの答えであなたがどんな種類のリンクを期待しているのかよく分かりません。 - Marcus Riemer
  • この回答にはplunkrが含まれていれば素晴らしい - Zze

28

私も同じ問題がありました。

loadChildrenを使用すると、ここでの答えはかなり良いです:

          {
             path: 'mypath',
             loadChildren : () => myModule
          }

https://github.com/angular/angular/issues/10958


  • これは動作しません .... - mp3por
  • わたしにはできる! - Alex Klaus
  • そのリンクは特に役立ちます。 - Zze
  • 正常に動作します。 @ mp3porはRC6から動作します。 - Sarat Chandra

1

私もこれを解決する方法を見つけました。基本的には、これまでのように私のルートを定義していますが、今回はトップレベルの子レベルで定義しています。たとえば、私の管理ルート:

const AdminRoutes: Routes = [
   {
      path: 'admin',
      component: AdminComponent,
      children: [
          ...setupRoutes
      ]
   }
]

export const adminRouting = RouterModule.forChild(AdminRoutes)

私のセットアップルートファイルは、より多くの子供を含む、それ自身のルートを定義するサブエリアからインポートされます。 catchは、このファイルがRouterModule.forChildの結果ではなく、 "Routes"オブジェクトをエクスポートするということです。

それがセットアップされた後、サブモジュール定義から子ルートと子子ルートが削除されました。私はその後、上記のMarcusのように、各サブモジュールからルートに使用されているすべてのコンポーネントをエクスポートしなければなりませんでした。私がそれをしたら、私は彼らが欲しいのと同じようにルートが働き始めました。

私の親モジュールは子モジュールのルートについてあまり知っていないので、私はこのソリューションが本当に好きだとは思わない。しかし、少なくともRC5のためのそれを回避するための簡単な方法、それはすべての場所のすべてのコンポーネントを漏らすことはありません。彼が私を正しい軌道に乗せたので、私は先に進み、答えとしてマークスの答えをマークします。


  • これは私のために働く、ありがとう! - Alex G
  • こんにちはジョン、あなたのアプローチは動作しますが、どのようにモジュールの遅延読み込みを扱うのですか?このアプローチでは、他のモジュールを遅延ロードできないようです - Alex G

1

私は2.0.0 rc5は今興味がないと思う。しかし、角度4で働いている、早すぎるかもしれません。

@NgModule({
    imports: [
        RouterModule.forRoot([
                {path: "", redirectTo: "test-sample", pathMatch: "full"},
                {
                    path: "test-sample",
                    loadChildren: () => TestSampleModule
                }
        ])
    ],
    exports: [RouterModule],
    declarations: [] 
}) 
export class AppRoutingModule{}

@NgModule({
    imports: [
        RouterModule.forChild([{
                    path: "",
                    component: TestSampleComponent,
                    children: [
                        {path: "", redirectTo: "home", pathMatch: "full"},
                        {
                            path: "home",
                            loadChildren: () => HomeModule
                        },
                        {
                            path: "about",
                            loadChildren: () => AboutModule
                        }
                    ]
                }
        ])
    ],
    exports: [RouterModule],
    declarations: []
})
export class TestSampleRoutingModule {}

@NgModule({
    imports: [RouterModule.forChild([{
                    path: "",
                    component: AboutComponent
                }
    ])],
    exports: [RouterModule]
})
export class AboutRoutingModule {}

アカウントを取るloadChildren: () => {...}。それは怠惰な読み込みではありません。

詳細はこちらをご覧くださいfeat:サポートNgModules階層sans Lazy Loading


0

ngModulesとRC5を使用している場合、親モジュールのルーティング設定では、子モジュールのルーティングについて何も知る必要はありません。ここでは、親モジュールのルートを定義するだけです。 さらに、子モジュールを親モジュールにインポートする必要があります。 子モジュールでは、このようにルートを定義する必要があります。

export const childRoutes: Routes = [
  {
    path: 'someChild',
      component: SomeChildComponent,
      children: [
        { path: '', component: SomeChildSubComponent1 },
        { path: 'comp1', component: SomeChildSubComponent1 },
        { path: 'comp2', component: SomeChildSubComponent2 }
      ]
  }
];

これにより、/ someParent / someChild / comp1のようなURLが作成され、コンポーネントは対応するルータのアウトレットに表示されます。 注:空のパスのコンポーネントを宣言する必要があります。それ以外の場合は、子供たちに移動することはできません。


  • これはネスティングの最初のレベルでのみ機能します。後続のすべてのレベルで、ルートはルートモジュールに追加され、親を介して到達できません。 - Thorsten Westheider
  • 高Torsten、残念ながらあなたは正しいです。親オブジェクトのパスを追加してルートオブジェクトのパス情報を変更すると、コンポーネントにアクセスできます。しかし、あなたは正しいルーターアウトレットでそれを見ないでしょう。それはあなたのソリューションの問題でもあるようです。バグかもしれない?これについて既に開いている問題がある場合、あなたは知っていますか? - westor
  • 私はそれが設計上のものだと思っています。遅延読み込みを使用して回避することができます。とにかくおそらくもっと良い解決策でしょう。 - Thorsten Westheider
  • この問題の進捗状況は?私はバージョン2.0.0で同じ問題に直面しました。 @ThorstenWestheider - Kinorsi

0

私はこれもうまく動作するようにしました。階層のすべての親コンポーネントを実際にレンダリングする必要がない限り、私のソリューションははるかにエレガントです。

私のアプローチを理解するための鍵は、ルートモジュールにモジュールがどれくらい深く入れ子になっていても、すべてのルートが必要であるということです。簡単な例ですが、DepartmentModuleEmployeeModuleこのURLを使用してナビゲートしたい

/department/1/employee/2

その時点で従業員2の詳細が表示されます。ルートの設定departmentdepartment.routing.tsそしてemployeeemployee.routing.ts意志ない私たちが意図した通りに働くと、あなたは

/employee/2

ルートコンポーネントから

/department/1/employee/2

クラッシュします(ルートが見つかりません)。このシナリオでの一般的なルート設定は、次のようになります。

export const departmentRoutes: Routes = [
    { path: 'department', component: DepartmentComponent, children: [
        { path: '', component: DepartmentsComponent },
        { path: ':id', component: DepartmentDetailsComponent }
    ]}
];

export const employeeRoutes: Routes = [
    { path: 'employee', component: EmployeeComponent, children: [
        { path: '', component: EmployeesComponent },
        { path: ':id', component: EmployeeDetailsComponent }
    ]}
];

そしてEmployeeModuleによって輸入されるDepartmentModule。今、私が言ったように、残念ながらそれは働かない。

ただし、変更を1回だけ行うと、次のようになります。

export const employeeRoutes: Routes = [
    { path: 'department/:id/employee', component: EmployeeComponent, children: [
        { path: '', component: EmployeesComponent },
        { path: ':id', component: EmployeeDetailsComponent }
    ]}
];

キャッチは、それですDepartmentModuleすぐにあなたはemployeeURLにはアクセスできますが、引き続きすべてのパラメータにアクセスできますActivatedRoute

export class EmployeeDetailsComponent {
    departmentId: number;
    employeeId: number;
    constructor(route: ActivatedRoute) {
        route.parent.params.subscribe(params =>
            this.departmentId= +params['id'])
        route.params.subscribe(params => 
            this.employeeId= +params['id']);
    }
}

私はこれが公式のアプローチになっているのだろうかと思っていますが、今はこれがAngular 2チームの次の急変する変更まで私の仕事です。


0

つかいますloadChildren。それで大丈夫です。しかし、ビルドプロセスを再開すると、ビルドエラーが発生します。エクスポートされたシンボルは、loadChildren

import { ChildModule } from './child/child.module';

export function childRouteFactory() {
  return ChildModule;
}

...
  {
    path: 'child',
    loadChildren: childRouteFactory
  }
...

リンクされた質問


関連する質問

最近の質問