MEANスタック入門(4) AngularとExpressの連携
今回はExpressで作成したAPIをAngularから実際に利用しつつ、Angularの基本的な開発方法に触れていきます。
project-name/src/app
配下で作業し、作業後の構成は以下のようになります。
app │ app-routing.module.ts │ app.component.html │ app.component.scss │ app.component.spec.ts │ app.component.ts │ app.module.ts │ ├─components │ └─call-express-api │ call-express-api.component.html │ call-express-api.component.scss │ call-express-api.component.spec.ts │ call-express-api.component.ts │ └─services call-express-api.service.spec.ts call-express-api.service.ts
Serviceの作成
Angularでは、各種APIへのアクセスはServiceから行います。
services
ディレクトリを作成し、Angular CLIのng g service
コマンドで必要ファイルを生成します。
ng g service
コマンドはカレントディレクトリに依存するので、services
ディレクトリまで移動してから実行します。
$ ng g service callExpressApi
実行すると以下の2ファイルが生成されます。
spec
のほうはテスト用なので、call-express-api.service.ts
のほうにAPIにアクセスするgetUsers
メソッドを実装します。
まず、HTTPアクセスに必要なHttp
クラスをインポートしてコンストラクタの引数に指定します。
また、Http.get
はObservable型の値を返すので、Observable.map
を使うためにrxjs/add/operator/map
をインポートします。
call-express-api.service.ts
import { Injectable } from '@angular/core'; import { Http } from '@angular/http'; import 'rxjs/add/operator/map'; @Injectable() export class CallExpressApiService { constructor( private http: Http ) { } getUsers() { return this.http.get("api/users") .map(response => response.json()); } }
上記ではapi/users
にアクセスしていますが、ng server
で実行している場合、Angularの簡易サーバとAPIサーバが別のポートで動いているので、Angular側からAPIを呼ぶと404のエラーになります。
また、ポートまで指定してAPIにアクセスした場合も、クロスオリジンのエラーで同じく実行出来ません。
これを回避するには、プロジェクトのルートディレクトリにproxy.conf.json
を作成し、ng server
実行時に--proxy-config
オプションで読み込ませます。
proxy.conf.json
{ "/api": { "target": "http://localhost:4300", "secure": false } }
$ ng server --proxy-config proxy.conf.json
これでポートの差異を意識せず開発出来るようになります。
Componentの作成
Componentはビューの部品のようなもので、各部品毎の表示や動作を定義します。
components
ディレクトリを作成し、Angular CLIのng g component
コマンドで必要ファイルを生成します。
ng g component
コマンドはng g service
と同じくカレントディレクトリに依存するので、components
ディレクトリまで移動してから実行します。
$ ng g component callExpressApi
実行するとcall-express-api
ディレクトリが生成され、その配下に以下4ファイルが生成されます。
- call-express-api.component.html
- call-express-api.component.scss
- call-express-api.component.ts
- call-express-api.component.spec.ts
call-express-api.component.ts
CallExpressApiComponent
クラスを作成し、先ほど作成したCallExpressApiService
を実行して、HTML表示用の変数に代入します。
CallExpressApiService
をインポートしてコンストラクタの引数に指定し、Serviceのインスタンスを生成するためにproviders
で読み込みます。これは、app.module.ts
でグローバルに読み込んでも動きますが、今回はこのComponentだけなのでここで読み込みます。
getUsers
はObservableを返すので、subscribe
メソッドでデータを受け取って変数users
に代入します。
call-express-api.component.ts
import { Component, OnInit } from '@angular/core'; import { CallExpressApiService } from '../../services/call-express-api.service'; @Component({ selector: 'app-call-express-api', templateUrl: './call-express-api.component.html', styleUrls: ['./call-express-api.component.scss'], providers: [CallExpressApiService] }) export class CallExpressApiComponent implements OnInit { users: any; constructor( private callExpressApiService: CallExpressApiService ) { } ngOnInit() { this.callExpressApiService.getUsers().subscribe(u => { this.users = u.users; }); } }
call-express-api.component.html
APIからの返答が代入された変数users
を利用して、内容を表示するHTMLを作成します。
配列を受けて要素の数だけ繰り返し表示させる場合、ngFor
ディレクティブを利用します。*
プレフィックスを付与することでtr
要素がテンプレート化され、そのテンプレートを元にusers
の各要素の内容が表示されます。
call-express-api.component.html
<table border="1"> <tr *ngFor="let user of users"> <td>{{user.id}}</td> <td>{{user.address}}</td> </tr> </table>
ルーティングの設定
初めに表示されるComponentはapp
直下にあるapp.component.html
です。
ここにナビゲーションを用意し、ナビゲーションをクリックするとヘッダーを残してコンテンツ部分が切り替わるような、いわゆるシングルページアプリケーションの構成にします。
routerLink
ディレクティブでURIを指定し、<router-outlet>
タグでコンテンツ表示位置を設定します。
app.component.html
<header> <h1 class="logo"><a href="/">MEAN</a></h1> <nav> <ul> <li><a routerLink="/users">Users</a></li> </ul> </nav> </header> <router-outlet></router-outlet>
Angularアプリをng new
で初めに生成する際、--routing=true
を付けているとapp
直下にapp-routing.module.ts
が生成され、app.module.ts
で既に読み込まれています。
このapp-routing.module.ts
に、ルーティングさせたいURIとComponentを記述します。
app-routing.module.ts
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { CallExpressApiComponent } from './components/call-express-api/call-express-api.component'; const routes: Routes = [ {path: 'users', component: CallExpressApiComponent}, ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
動作確認
ng server
で実行している場合のAngular側のテストは、http://localhost:4200にアクセスします。
Usersのリンクをクリックすると、APIのレスポンスを受けてテーブルが表示されます。
ビルド後はdist
ディレクトリのclient
配下のファイルも揃うので、dist/server/bin/www.js
を実行するだけでhttp://localhost:4300からclient
配下のファイルも提供されます。