web-dev-qa-db-ja.com

モジュールの子としてモジュールにルーティングする方法-Angular 2 RC 5

現在作業中のアプリケーションを最新の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つのモジュールにあるルートに関するエラーが発生しました。明らかにこれは新しくリリースされたため、これらのケースのいくつかに関するドキュメントは少し制限されています。

誰でも提供できるヘルプは大歓迎です!

61
John Ackerman

さて、週末の大部分でこれをいじくり回した後、私はそれを最後に実行しました。最終的に私のために働いたのは、以下を行うことでした

  • ルーティングするすべてのモジュールのすべてのRoutesname__をエクスポートします。子モジュールのRouterModule.forChild()をインポートしないでください。
  • エクスポートevery子モジュール定義の子ルート定義から見えるコンポーネント。
  • 通常どおり、すべての子ルートをインポート(TypeScript importname__キーワードを意味)し、...演算子を使用してこれらを正しいパスに組み込みます。パスを定義する子モジュールで動作させることはできませんでしたが、親でそれを使用することは問題なく機能します(遅延読み込みと互換性があります)。

私の場合、このような階層には3つのレベルがありました。

  • ルート(/
    • エディター(editor/:projectId
      • クエリ(query/:queryId
      • ページ(page/:pageId
    • フロント(aboutname__)

/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 }
    ]
}

ただし、これを機能させるには、一般的なEditorname__がQueryEditorname__をインポートandする必要があり、QueryEditorname__はQueryCreateComponentname__およびQueryEditorComponentname__をインポートする必要があります。これを行わないと、Component XYZ is defined in multiple modulesの行に沿ってエラーが発生します。

遅延読み込みもこのセットアップで正常に機能することに注意してください。その場合、子ルートはもちろんインポートされません。

51
Marcus Riemer

同じ問題がありました。

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

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

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

32
Jklf

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: () => {...}を考慮してください。遅延読み込みではありません。

詳細については、 feat:Lazy Loadingを使用しないNgModules階層のサポート

2
Leonid Gorshkov

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

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

export const adminRouting = RouterModule.forChild(AdminRoutes)

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

セットアップが完了したら、サブモジュール定義から子ルートとサブ子ルートを削除しました。次に、上記のMarcusのように、ルートで使用されるすべてのコンポーネントを各サブモジュールからエクスポートする必要がありました。それをやると、ルートは私が望んでいたように機能し始めました。

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

1
John Ackerman

loadChildrenを使用します。それで大丈夫です。ただし、ビルドプロセスを再起動すると、ビルドエラーが発生します。エクスポートされたシンボルをloadChildrenに一致させる必要があります。

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

export function childRouteFactory() {
  return ChildModule;
}

...
  {
    path: 'child',
    loadChildren: childRouteFactory
  }
...
0
Jehong Ahn

これも機能するようになり、実際に階層内のすべての親コンポーネントをレンダリングする必要がない限り、私のソリューションははるかにエレガントだと思います。

私のアプローチを理解するための鍵は、どのくらい深くネストされたモジュールがルートモジュールに追加されるかに関係なく、すべてのルートです。簡単な例、このURLを使用してナビゲートしたいDepartmentModuleEmployeeModuleがあるとします

/department/1/employee/2

その時点で、従業員2の詳細が表示されます。 department.routing.tsdepartmentおよびemployee.routing.tsemployeeのルートを構成すると、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 }
    ]}
];

EmployeeModuleDepartmentModuleによってインポートされます。さて、私が言ったように、それは残念ながら機能しません。

ただし、たった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チームからの次の重大な変更まで有効です。

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が得られ、コンポーネントが対応するルーターアウトレットに表示されます。注:空のパスのコンポーネントを除外する必要があります。そうでなければ、あなたはあなたの子供にナビゲートすることができません。

0
westor