⛳
Angularのmoduleでネストしたルーティングをやってみた
やりたかったこと
/admin
のように、特定のパス以下でのルーティングやファイル群をmoduleにまとめたい。
ベースアプリ
公式チュートリアルをやっていたので、これをリファクタリングした。
やったこと
1: 子ページのRoutingモジュールを作成
子ページにしたいコンポーネントのインポートとRouteの定義を実施。
ネスト先の場合、RouterModule
はforChild
を使う。
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HeroesComponent } from './heroes/heroes.component';
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
import { DashboardComponent } from './dashboard/dashboard.component';
const heroesRoutes: Routes = [
{
path: '',
component: HeroesComponent,
},
{
path: 'dashboard',
component: DashboardComponent,
},
{
path: ':id',
component: HeroDetailComponent,
},
];
@NgModule({
declarations: [],
imports: [RouterModule.forChild(heroesRoutes)],
exports: [RouterModule],
})
export class HeroesRoutingModule {}
2: 子ページのmoduleも作っておく
moduleの中身もapp.module.ts
から移動させる。
HeroService
をproviders
に追加しないと、AppModules
からHttpClientModule
を剥がせなかった。
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InMemoryDataService } from '../in-memory-data.service';
import { DashboardComponent } from './dashboard/dashboard.component';
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
import { HeroSearchComponent } from './hero-search/hero-search.component';
import { HeroesRoutingModule } from './heroes-routing.module';
import { HeroService } from './heroes/hero.service';
import { HeroesComponent } from './heroes/heroes.component';
@NgModule({
declarations: [
HeroesComponent,
HeroDetailComponent,
HeroSearchComponent,
DashboardComponent,
],
imports: [
CommonModule,
FormsModule,
HeroesRoutingModule,
HttpClientModule,
HttpClientInMemoryWebApiModule.forRoot(InMemoryDataService, {
dataEncapsulation: false,
}),
],
exports: [
HeroesComponent,
HeroDetailComponent,
HeroSearchComponent,
DashboardComponent,
],
providers: [HeroService],
})
export class HeroesModule {}
app-routing.module.ts
で子ページのモジュールを読み込む
3: 読み込みたいパスで、loadChildren
を使ってモジュールをimportする。
loadChildren
で読み込むファイルパスを文字列で指定する記事もありますが、今回のAngular v14以降ではDynamic importでやる必要がありました。
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{
path: 'heroes',
loadChildren: () =>
import('./heroes/heroes.module').then((m) => m.HeroesModule),
},
{
path: '',
redirectTo: '/heroes/dashboard',
pathMatch: 'full',
},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
app.modules.ts
を整理
4: 移動させたモジュールやコンポーネントを消します。
ここで子ページのモジュールをimportするとバグるので要注意。
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { MessagesComponent } from './messages/messages.component';
@NgModule({
declarations: [AppComponent, MessagesComponent],
imports: [BrowserModule, AppRoutingModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
感想
後からモジュール化したのでちょっと手間でしたが、先にモジュールがある状態ならばCLIでのgenereteでよしなにやってくれるのではと期待しています。
実際にやる場合は、Serviceについても別Moduleにしておいた方が使いやすそうかも?
参考
Discussion