【Angular】公式チュートリアルの理解２ (ナビゲーションの追加)

# はじめに
https://qiita.com/s-umbys/items/46fc7c051a6456c6f4c8

前記事でAngular公式チュートリアルの1-入門を終え、Angularの基本について理解をした。続けて「ナビゲーションの追加」を通して理解を深めていく。

このセクションを通して、web上でのURL遷移（画面遷移）の設定方法を学んでいく。前回が理解できていれば今回はそこまで詰まることなく進めることができると思う。

# URLパスをコンポーネントに関連付ける
まず、前回同様Componentを生成する。
```sh:ターミナルでの実行
ng generate component product-details
```
## app.module.tsでルーティングの設定
ルーティングはルートモジュールであるapp.module.tsで設定を行う。具体的には、`RouterModule.forRoot`の中に`pathとcomponent`を含む配列で指定する。
ここではpathに`products/:productId`と指定しているが、`:`がつくのは:(コロン)以下がプレースホルダ(値の入れ物、変数のような認識でよい)であるという意味を示す。
これによってコンポーネントとURLパスを関連付ける事ができる。
```ts:src/app/app.module.ts
@NgModule({
  imports: [
    BrowserModule,
    ReactiveFormsModule,
    RouterModule.forRoot([
      { path: '', component: ProductListComponent },
      //ここに新たに追加
      { path: 'products/:productId', component: ProductDetailsComponent },
    ])
  ],
  declarations: [
    AppComponent,
    TopBarComponent,
    ProductListComponent,
    ProductAlertsComponent,
    ProductDetailsComponent,
  ],
```

## リンクの設定方法：`aタグに[routerLink]を設定する`
次に上記で設定したURLへ飛ぶよう設定を行う。今回は`product-listコンポーネント`の`product.name`を押すと遷移させる。
Angularでは`aタグに[routerLink]を設定する`。routerLinkには上記のapp.moduleで指定したpathを設定する。`'/product'`は固定文字列、`product.id`はproductごとに変化する値である。
ここでは、一般的なhtmlの`aタグのhref属性`のURLリンク設定と同義だという認識で良い。
```html:src/app/product-list/product-list.component.html
<div *ngFor="let product of products">
  <h3>
   <!-- この部分を編集-->
    <a
      [title]="product.name + ' details'"
      [routerLink]="['/products', product.id]">
      {{ product.name }}
    </a>
  </h3>
</div>
```
こうして商品名をクリックするとページ遷移が確認でき、URLを見ると上記で設定したものとなっている。
以上のようにapp.moduleファイルでURLとcomponentをつなげる設定をし、htmlファイルでリンク設定を行うことでルーティングの設定が可能となる。

# 商品の詳細を見る
続いて上記のページ遷移後のページを作成する。
ここで必要なことは、遷移後のComponentにどの商品を表示させるかを設定することである。具体的には、上記で設定したURLからproductIdの値を渡すということである。

##　詳細Componentの編集
```ts:src/app/product-details/product-details.component.ts
import { Component, OnInit } from '@angular/core';
//ActivatedRouteというクラス。ルーティングに関する情報を持っている。次で使う。
import { ActivatedRoute } from '@angular/router';
//これまで通りproductをimport。products.tsでproductsでexportされている配列をProductとして当ファイルで用いるということ
import { Product, products } from '../products';

export class ProductDetailsComponent implements OnInit {
  product: Product | undefined;
  //クラスなのでインスタンス化が必要
  constructor(private route: ActivatedRoute) { }
  /* ... */
}
```
ここで注入という単語が初めて出てくるが、[前回](https://qiita.com/s-umbys/items/46fc7c051a6456c6f4c8)でも多少記述したとおり、当ファイルでクラスやサービスを利用できるようにインスタンス化するというような認識で問題ない。
インスタンス化は`consutructorの引数`に指定する。
上記コメントにコードの説明を記述しておく。基本的にはJavaScriptの書き方なので適宜調べると細かくわかる。

## ActivateRouteクラスを用いてproductIdを取り出す
まず、下記の`ngOnit()メソッド`を追加する。
コードの意味はコメントにて追記しておく。やりたいことはproductIdを取り出し、products配列から対応する商品を取得することである。ルートパラメータという言葉が出てくるがこれはURLの末尾の値を取得するということ。つまり今回はproductIdを取得することである。

なお、`コンストラクタ`と`ngOnit()メソッド`の違いは、前者はコンポーネント作成途中に実行されるもの、後者は作成後に最初に実行されるもの、と認識している。
```ts:src/app/product-details/product-details.component.ts
ngOnInit() {
  // First get the product id from the current route.
  // routeインスタンスのsnapshot.paramMapでURLを取得できる(そういうものだという理解でOK)
  const routeParams = this.route.snapshot.paramMap;
  // oute.snapshot.paramMap.getメソッドで取得したURLからproductIdを取り出し、number型へと変換
  const productIdFromRoute = Number(routeParams.get('productId'));

  // Find the product that correspond with the id provided in route.
  // find関数を用いてidが一致するproductを変数に代入
  this.product = products.find(product => product.id === productIdFromRoute);
}
```

## 詳細ページの作成
*ngIfディレクティブを用いて商品が存在する場合表示させる。

```html:src/app/product-details/product-details.component.html
<h2>Product Details</h2>

<div *ngIf="product">
  <h3>{{ product.name }}</h3>
  <h4>{{ product.price | currency }}</h4>
  <p>{{ product.description }}</p>
</div>
```
ここで新しくパイプ` | `という方法が新しく出てくるが、公式ドキュメントの通り`HTMLテンプレート内のデータを変換する方法`である。`currency`パイプを用いることで数値から通貨文字列に変換している。currency 自体が重要ではなくパイプという方式が重要で、他にもHTML上で様々な値や文字列へと変換するために利用する機会が多く？覚えていたほうがいいかもしれない。

こうしてページ遷移先に商品詳細が表示されたら完了である。



# おわりに
Angular公式チュートリアルの2として`ナビゲーションの追加`セクションを進めてきた。今回は前回と比較してどういった動きをしているのか理解しやすかったように思える。特にルーティングは今後必ず出てくると考えられるので再度読み込み、復習することで理解を深めることが重要に思える。

下記リンクより、引き続きチュートリアルを進めていきたい。
次→[【Angular】公式チュートリアルの理解3 (データの管理①)](https://qiita.com/s-umbys/items/46b2b3075009d0217468 "【Angular】公式チュートリアルの理解3 (データの管理①)")