AngularはSPAのフレームワークなので動的処理は基本的にサーバ側APIとのやり取りになります。
ここでは簡単なCRUD処理を試してみます。
簡単なAPIサーバの実装
まず、expressを利用して簡単なテスト用APIサーバを実装します。
Angular-Inmemory-Web-Apiという仕組みもありますが、ここではexpressを利用します。
作用場の確保と必要モジュールのインストール
作業場を用意して実装ファイルであるindex.jsを作成します。
mkdir rest-server
cd rest-server
npm init -y
npm install express
touch index.js
実装
index.jsに対し、下記のような実装をします。
DBは利用せずメモリ内の配列を利用します(データはサーバを落とせば永続化されません)。
var express = require('express');
var app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
//CROS対応(何でも許可:実運用ではこんなことしちゃだめ)
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "*")
res.header("Access-Control-Allow-Headers", "*");
next();
});
//サーバ起動
app.listen(3000, function () {
console.log("Start on port 3000.")
});
//サンプルデータ
let users = [
{ id: 1, name: "User1", email: "user1@test.local" },
{ id: 2, name: "User2", email: "user2@test.local" },
{ id: 3, name: "User3", email: "user3@test.local" }
];
//一覧取得
app.get('/users', function (req, res) {
res.send(JSON.stringify(users));
});
//追加
app.post('/users', function (req, res) {
users.push(req.body);
res.send(JSON.stringify({ status: "OK" }))
});
//idで指定したuserを取得
app.get('/users/:id', function (req, res) {
for (let i = 0; i < users.length; i++) {
if (users[i].id == req.params.id) {
res.send(JSON.stringify(users[i]));
}
}
});
//指定したidを更新
app.post('/users/:id', function (req, res) {
for (let i = 0; i < users.length; i++) {
if (users[i].id == req.params.id) {
users[i] = req.body;
}
}
res.send(JSON.stringify({ status: "OK" }))
});
//削除
app.delete('/users/:id', function (req, res) {
for (let i = 0; i < users.length; i++) {
if (users[i].id == req.params.id) {
users.splice(i, 1);
}
}
res.send(JSON.stringify({ status: "OK" }))
})
実行
実装したら実行して動作を確認します。
node index.js
終了はctr + cで。
テスト
curlを使って動作チェックをしておきます。
#全件取得
curl -s -X GET http://localhost:3000/users | python -mjson.tool
#指定ID取得
curl -s -X GET http://127.0.0.1:3000/users/1 | python -mjson.tool
#追加
curl -s -X POST -H 'Content-Type: application/json' -d '{"id":4,"name":"User4","email":"user4@test.local"}' http://127.0.0.1:3000/users
#更新
curl -s -X POST -H 'Content-Type: application/json' -d '{"id":4,"name":"User4_Updated","email":"user4@test.local"}' http://127.0.0.1:3000/users/4
#削除
curl -s -X DELETE http://127.0.0.1:3000/users/4
クライアント(Angular)側実装
APIの動作チェックが終わったらAngularでクライアント側を実装します。
完成イメージ
下記のようなテスト用の画面を実装します。
作業場の準備
まずは作業場を作成
ng new api-client
cd api-client
serviceの作成
通信処理を実装するためのserviceを生成します。名前は何もいいですがdataとしました。
ng generate service data
モデルの作成
今回はForm処理にテンプレート駆動型Formを利用するのでモデルを生成しておきます。場所はapp直下にします。
touch user.ts
user.tsに下記を記述します。
export class User {
id: number;
name: string;
email: string;
}
app.module.ts
続いて上記サービスの他、必要なモジュールを読み込みます。
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
//追加
import { DataService } from './data.service';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule } from '@angular/forms';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule, //追加
FormsModule //追加
],
providers: [
DataService //追加
],
bootstrap: [AppComponent]
})
export class AppModule { }
data.service.ts
サービスを実装します。
import { Injectable } from '@angular/core';
//追加
import { User } from './user';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class DataService {
users: User[];
private url = "http://127.0.0.1:3000";
constructor(
private http: HttpClient
) { }
getUsers(): Observable<User[]> {
return this.http.get<User[]>(`${this.url}/users`);
}
getUser(id: number): Observable<User> {
return this.http.get<User>(`${this.url}/users/${id}`)
}
setUser(user: User): Observable<User> {
return this.http.post<User>(`${this.url}/users`, user);
}
updateUser(user: User): Observable<User> {
return this.http.post<User>(`${this.url}/users/${user.id}`, user);
}
deleteUser(user: User): Observable<User> {
return this.http.delete<User>(`${this.url}/users/${user.id}`);
}
}
エラー処理は省いてます。
app.component.ts
続いてcomponent.tsにサービスを呼び出しを実装します。今回はapp.component.tsに直接書いています。
import { Component } from '@angular/core';
//追加
import { User } from './user';
import { DataService } from './data.service';
import { NgForm } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'rest-client';
users: User[];
user: User = { id: 4, name: 'User4', email: 'user4@test.local' };
form: NgForm;
constructor(
private service: DataService
) { }
getUsers(): void {
this.service.getUsers().subscribe(res => {
this.users = res;
})
}
getUser(id: number): void {
this.service.getUser(id).subscribe(res => {
console.log(JSON.stringify(res));
})
}
setUser(form: User): void {
this.service.setUser(form).subscribe(res => {
console.log(res);
})
}
updateUser(form: User): void {
this.service.updateUser(form).subscribe(res => {
console.log(res);
})
}
deleteUser(form: User): void {
this.service.deleteUser(form).subscribe(res => {
console.log(res);
})
}
}
app.component.html
最後にHTMLを仕上げます。
<h3>取得</h3>
<button (click)="getUsers()">データ取得</button>
<ul *ngFor="let user of users">
<li>{{user.id}} {{user.name}}</li>
</ul>
<h3>追加</h3>
<form #form=ngForm (ngSubmit)="setUser(form.value)">
id:<input type="text" value="4" name="id" [ngModel]="user.id"><br>
name:<input type="text" value="sasaki" name="name" [ngModel]="user.name"><br>
email:<input type="text" value="sasaki@test.com" name="email" [ngModel]="user.email"><br>
<button>登録</button>
</form>
<h3>編集</h3>
<button (click)="updateUser(form.value)">編集</button>
<h3>削除</h3>
<button (click)="deleteUser(form.value)">削除</button>
<h3>取得</h3>
<button (click)="getUser(1)">取得(1)</button>
動作確認
動作確認をします。
ng serve --open
おまけ
headerをカスタマイズする
下記はmicroCRMのAPIにリクエストを投げている例。
import { Injectable } from '@angular/core';
//追加
import { User } from './user';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class DataService {
users: User[];
private url = "http://127.0.0.1:3000";
//Header
private httpOptions: any = {
headers: new HttpHeaders({
'X-API-KEY': 'xxxxxxx-fbc3-49ac-a1dd-xxxxxxxxxx' //keyは変えてね
}),
body: null
}
constructor(
private http: HttpClient
) { }
getLogo(): Observable<any> {
return this.http.get<any>(`https://etco.microcms.io/api/v1/logo`, this.httpOptions);
}
}