3
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Angular入門:APIのとのやり取り

Last updated at Posted at 2021-02-09

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は利用せずメモリ内の配列を利用します(データはサーバを落とせば永続化されません)。

index.js
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でクライアント側を実装します。

完成イメージ

下記のようなテスト用の画面を実装します。

スクリーンショット 2021-01-27 8.54.14.png

作業場の準備

まずは作業場を作成

ng new api-client
cd api-client

serviceの作成

通信処理を実装するためのserviceを生成します。名前は何もいいですがdataとしました。

ng generate service data

モデルの作成

今回はForm処理にテンプレート駆動型Formを利用するのでモデルを生成しておきます。場所はapp直下にします。

touch user.ts

user.tsに下記を記述します。

app/user.ts
export class User {
    id: number;
    name: string;
    email: string;
}

app.module.ts

続いて上記サービスの他、必要なモジュールを読み込みます。

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

サービスを実装します。

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に直接書いています。

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を仕上げます。

app.component.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にリクエストを投げている例。

data.service.ts
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);
  }
}

3
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?