現在作業中のアプリケーションを最新の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",
私のアプリはモジュールの構成として構築されており、いくつかのモジュールが親モジュールの子として接着されています。たとえば、通知モジュール、ユーザーモジュール、および電話モジュール(たとえば)で構成される管理モジュールがあります。これらのモジュールへのルートは次のようになります...
/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}
]
}
]
これはすべて非常にうまくいきました。モジュールにアップグレードする過程で、代わりにすべてを個別のルーティングファイルに移動したので、これら2つは次のようになります
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つのモジュールにあるルートに関するエラーが発生しました。明らかにこれは新しくリリースされたため、これらのケースのいくつかに関するドキュメントは少し制限されています。
誰でも提供できるヘルプは大歓迎です!
さて、週末の大部分でこれをいじくり回した後、私はそれを最後に実行しました。最終的に私のために働いたのは、以下を行うことでした
Routes
name__をエクスポートします。子モジュールのRouterModule.forChild()
をインポートしないでください。import
name__キーワードを意味)し、...
演算子を使用してこれらを正しいパスに組み込みます。パスを定義する子モジュールで動作させることはできませんでしたが、親でそれを使用することは問題なく機能します(遅延読み込みと互換性があります)。私の場合、このような階層には3つのレベルがありました。
/
)editor/:projectId
)query/:queryId
)page/:pageId
)about
name__)/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
name__がQueryEditor
name__をインポートandする必要があり、QueryEditor
name__はQueryCreateComponent
name__およびQueryEditorComponent
name__をインポートする必要があります。これを行わないと、Component XYZ is defined in multiple modules
の行に沿ってエラーが発生します。
遅延読み込みもこのセットアップで正常に機能することに注意してください。その場合、子ルートはもちろんインポートされません。
同じ問題がありました。
ここでの答えは、loadChildrenを使用してかなり良いです:
{
path: 'mypath',
loadChildren : () => myModule
}
2.0.0 rc5は今は興味がないと思います。しかし、Angular 4で機能しますが、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: () => {...}
を考慮してください。遅延読み込みではありません。
私もこれを解決する方法を見つけました。基本的に、以前と同じ方法でルートを定義していますが、今回は最上位の子レベルで定義しています。たとえば、私の管理ルート:
const AdminRoutes: Routes = [
{
path: 'admin',
component: AdminComponent,
children: [
...setupRoutes
]
}
]
export const adminRouting = RouterModule.forChild(AdminRoutes)
私のセットアップルートファイルはサブエリアからインポートされます。サブエリアは、より多くの子を含む独自のルートを定義します。問題は、このファイルがRouterModule.forChildの結果ではなく、「Routes」オブジェクトをエクスポートすることです。
セットアップが完了したら、サブモジュール定義から子ルートとサブ子ルートを削除しました。次に、上記のMarcusのように、ルートで使用されるすべてのコンポーネントを各サブモジュールからエクスポートする必要がありました。それをやると、ルートは私が望んでいたように機能し始めました。
私の親モジュールは子モジュールのルートについてあまりにも多く知っているので、私はこのソリューションが本当に好きだとは思わない。しかし、少なくともRC5で簡単に回避できる方法であり、すべてのコンポーネントが至る所に漏れることはありません。彼が私を正しい道に導いたので、先に進み、マーカスの答えを答えとしてマークします。
loadChildren
を使用します。それで大丈夫です。ただし、ビルドプロセスを再起動すると、ビルドエラーが発生します。エクスポートされたシンボルをloadChildren
に一致させる必要があります。
import { ChildModule } from './child/child.module';
export function childRouteFactory() {
return ChildModule;
}
...
{
path: 'child',
loadChildren: childRouteFactory
}
...
これも機能するようになり、実際に階層内のすべての親コンポーネントをレンダリングする必要がない限り、私のソリューションははるかにエレガントだと思います。
私のアプローチを理解するための鍵は、どのくらい深くネストされたモジュールがルートモジュールに追加されるかに関係なく、すべてのルートです。簡単な例、このURLを使用してナビゲートしたいDepartmentModule
とEmployeeModule
があるとします
/department/1/employee/2
その時点で、従業員2の詳細が表示されます。 department.routing.ts
のdepartment
およびemployee.routing.ts
のemployee
のルートを構成すると、notは意図したとおりに動作し、
/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
URLに移動するとすぐにemployee
がアクティブにならないことですが、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チームからの次の重大な変更まで有効です。
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が得られ、コンポーネントが対応するルーターアウトレットに表示されます。注:空のパスのコンポーネントを除外する必要があります。そうでなければ、あなたはあなたの子供にナビゲートすることができません。