Angular Rooter (サブモジュールの使い方)

# Augularでのルーティングで以下の事が困ったのでまとめ
- 複数のルーティング基点を作りたい (今回)
- LazyLoadと認証ありなしでルーティングを分ける方法 (次回)

# どんな事をしたいのか？

<img width="767" alt="Screen Shot 2018-01-21 at 0.48.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/94948/04c8e26f-a1ae-be4a-24ab-c452e848436f.png">


<img width="741" alt="Screen Shot 2018-01-21 at 0.49.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/94948/ff9f3ef2-3041-eb78-474a-c09ea551a841.png">


[ソースコード(Github)](https://github.com/kotar0/qiita_angular_router)とDemo(準備中)
※cssのgridを使用しています。ChromeかFirefoxで確認お願いします。


# routerの設定

**全ての親となるルーター**  

```typescript:app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HelloComponent } from './hello/hello.component'

const routes: Routes = [
    { path:'', component:HelloComponent},
    { path:'shape', loadChildren:'./shapes/shapes.module#ShapesModule' }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

```
LazyLoadで読み込みたいモジュールは、
```
{ path:'shape', loadChildren:'./shapes/shapes.module#ShapesModule' }
```
と指定する。

※注意1: LazyLoad対象のComponentとModuleはimportしない。するとバンドルされてします。
※注意2: Moduleのパスはapp/からはじめているチュートリアルもあり、実際何がベスト・プラクティスなのか分からない。今回はこれで動いた。

**子供となるルーター**  

```typescript:shape-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { ShapeComponent } from '../shape/shape.component'
import { RectangleComponent } from '../rectangle/rectangle.component'
import { CircleComponent } from '../circle/circle.component'


const routes: Routes = [
    { path:'', component:ShapeComponent,
        children:[
            { path:'rectangle', component:RectangleComponent },
            { path:'circle', component:CircleComponent }
        ]
    }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class ShapesRoutingModule { }
```

forRoot関数ではなく、forChild関数を使用する。しかし、AngularCliを使ってmoduleを生成すればこの用に表記してあるので、そんなに心配しなくても大丈夫です。
```
imports: [RouterModule.forChild(routes)],
```

# router-outletについて
今回の場合、router-outletはapp.component.htmlとshape.component.htmlに記述します。

```html:app.component.html
<nav class="commonHeaderNavigation">
    <div class="navItem logo">
        RoutingDemo
    </div>
    <div class="navItemContainer">
        <a class="navItem" routerLink="/">
            to top
        </a>
        <a routerLink="shape" class="navItem">to shape</a>
    </div>
</nav>


<router-outlet></router-outlet>


<footer class="commonFooter">
    <div class="footerItem">
        demo by kota0
    </div>
</footer>
```

```html:shape.component.html
<div class="container">
    <div class="sideMenu">
        <a routerLink="./rectangle" class="linkItem">to rectangle</a>
        <a routerLink="./circle" class="linkItem">to circle</a>
    </div>
    <div class="routerContainer">


        <router-outlet></router-outlet>


    </div>
</div>
```

router-outletタグの中にcomponentが読み込まれ描画されるのかと思っていたのですが、そうではなく、router-outletタグの直下に展開されます。ですので、表示領域を限られた範囲にしておきたい場合は、下記のようにrouter-outletをラッピングすると便利でした。

```html
<div class="routerContainer">
    <router-outlet></router-outlet>
</div>
```

展開されたHTMLを見てみると、router-outletの兄弟要素としてapp-shapeや、app-rectangleが配置されています。
<img width="369" alt="Screen Shot 2018-01-21 at 9.40.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/94948/248db37e-569a-5904-21b6-91edfd8aea93.png">

# LazyLoadについて
親ルーター（app-routing.module.ts）で、下記のように指定しているとビルドされるJSファイルが別に生成され、リクエストが発生するまではクライアント側にソースが渡されません。

```
{ path:'shape', loadChildren:'./shapes/shapes.module#ShapesModule' }
```

# 認証系のとの組み合わせについて
認証が通らないとページを描画しないなどの処理もAngularに存在します。
こちらから(準備中)