Angularの基礎(API連係)

要点

Angularの学習として、今後アプリケーションを作っていくに当てって、4つのポイントで要点をまとめました。

  1. 基本構成
  2. ルーティングによる画面遷移
  3. ルーティングを使わない画面遷移
  4. API連係

この記事では4について記録しておきたいと思います。

前提

以前に紹介したDockerの環境で「sample03」プロジェクトを新たに作成します。

連係するAPIについては、AWSのLambdaとAPI Gatewayでテスト用のものを用意します。

APIの用意

AWS Lambda

コンソールからAWS Lambdaに遷移して、「関数の作成」を押下します。

オプションで「一から作成」を選択して、関数名を「myTest」、ランタイムは「Node.js 20.x」、アーキテクチャは「x86_64」、アクセス権限はデフォルトのままで「関数の作成」ボタンを押下します。

「myTest」関数ができたら、「コード」タブで以下のコードを入力します。

export const handler = async (event) => {
  // TODO implement
  const response = {
    statusCode: 200,
    body: {
      users: [
        {username: 'test1', firstname: '太郎', lastname: '東北', email: 'test1@example.com'},
        {username: 'test2', firstname: '次郎', lastname: '宮城', email: 'test2@example.com'},
        {username: 'test3', firstname: '花子', lastname: '仙台', email: 'test3@example.com'},
      ]
    },
  };
  return response;
};

Deployしたら、テストで正常に動作することを確認します。

API Gateway

APIを作成

コンソールからAPI Gatewayに遷移して、「REST API」を選択して「構築」ボタンを押下します。

「新しいAPI」でAPI名は「myTestAPI」、APIエンドポイントタイプは「リージョン」として「APIを作成」ボタンを押下します。

メソッドを作成

「メソッドを作成」を押下し、メソッドタイプは「GET」、統合タイプは「Lambda関数」、Lambda関数は先ほど作成した「myTest」関数を選択します。

他はデフォルトのままで「メソッドを作成」ボタンを押下します。

CORSを設定

「CORSを有効にする」ボタンを押下して、設定画面に遷移します。

ゲートウェイのレスポンスは4xx、5xx両方を対象。

許可するメソッドは「GET」。

今回は一時的なテスト用なので、originは全て許容します。

「保存」ボタンを押下して、設定を確定します。

※不正アクセスなどの危険性があるので、使い終わったらAPIを削除しましょう。

APIをデプロイ

「APIをデプロイ」ボタンを押下して、設定ウィンドウを表示します。

ステージは「新しいステージ」を選択して、ステージ名は「test」とします。

「デプロイ」ボタンを押下して、デプロイします。

APIをテスト

コンソールにAPIのエンドポイントが表示されているので、それをコピーして、ブラウザで実行してみます。

Angularのコーディング

モデルクラスを作成

データを格納するモデルクラスを作成

作成先として、/src/app/model のフォルダを作り、その下にuserクラスを展開。

ターミナルで以下コマンドを実行します。

ng generate class model/user --type=model

/src/app/model/user.model.ts ファイルが作成されます。

user.model.tsを編集

/src/app/mode/user.model.ts を以下のように編集。

export class User {
  constructor(public username: string, public firstname: string, public lastname: string, public email: string) {}
}

コンストラクタで変数定義をします。

データを表示する画面を作成

user-listコンポーネントを作成

ターミナルで以下コマンドを実行

ng generate component user-list

/src/app/user-listのコンポーネント一式が作成されます。

user-list.component.tsを編集

/src/app/user-list/user-list.component.tsを以下のように編集。

import { Component } from '@angular/core';

import { User } from '../model/user.model';
import { NgFor } from '@angular/common';

@Component({
  selector: 'app-user-list',
  standalone: true,
  imports: [NgFor],
  templateUrl: './user-list.component.html',
  styleUrl: './user-list.component.css'
})
export class UserListComponent {

}

UserモデルクラスとNgForディレクティブをインポートする。

(中間確認用)データをオンコード

APIと連係する前に、内部処理の理解のために、データをオンコードします。

/src/app/user-list/user-list.component.ts を以下のように編集。

import { Component } from '@angular/core';

import { User } from '../model/user.model';
import { NgFor } from '@angular/common';

@Component({
  selector: 'app-user-list',
  standalone: true,
  imports: [NgFor],
  templateUrl: './user-list.component.html',
  styleUrl: './user-list.component.css'
})
export class UserListComponent {
  users: User[] = [];

  ngOnInit() {
    let user1 = new User('user1', '一郎', '佐藤', 'sato@example.com');
    let user2 = new User('user2', '二郎', '鈴木', 'suzuki@example.com');
    this.users.push(user1);
    this.users.push(user2);
  }
}

users配列を用意して、初期処理(ライフサイクルフック)で固定データをセットしています。

user-list.component.htmlを編集

/src/app/user-list/user-list.component.html を以下のように編集。

<h3>APIの接続結果</h3>
<div>一覧表示</div>
<table>
  <thead>
    <tr>
      <th>username</th>
      <th>firstname</th>
      <th>lastname</th>
      <th>email</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let user of users">
      <td>{{ user.username }}</td>
      <td>{{ user.firstname }}</td>
      <td>{{ user.lastname }}</td>
      <td>{{ user.email }}</td>
    </tr>
  </tbody>
</table>

NgForディレクティブを使って、データ件数分をループさせてます。

app.component.tsを編集

/src/app/app.component.ts を以下のように編集。

import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';

import { UserListComponent } from './user-list/user-list.component';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet, UserListComponent],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})
export class AppComponent {
  title = 'sample03';
}

user-listコンポーネントをインポート。

app.component.htmlを編集

/src/app/app.component.html を以下のように編集。

<h1>API連係テスト</h1>
<app-user-list></app-user-list>

user-list.component.html を画面表示。

結果確認

「ng serve --host 0.0.0.0」をコマンド実行して、ブラウザで確認。

固定データが一覧で表示されました。

API連係を実装

API連係用のサービスクラスを作成

作成先として、/src/app/api のフォルダを作り、その下にuserクラスを展開。

ターミナルで以下コマンドを実行します。

ng generate service api/users

/src/app/api/users.service.ts ファイルが作成されます。

users.service.tsを編集

/src/app/api/users.service.tsを以下のように編集。

import { Injectable } from '@angular/core';

import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { User } from '../model/user.model';

@Injectable({
  providedIn: 'root'
})
export class UsersService {

  users: User[] = [];

  constructor(private httpCient: HttpClient) {}

  getUsers = ():Observable<User[]> => {
    return this.httpCient.get<User[]>('https://tx4y6a1yj8.execute-api.ap-northeast-1.amazonaws.com/test');
  }
}

API連係するために HttpClient をインポート。

非同期処理のために Observable をインポート。(Promiseで処理することもできるらしいが、今回はObservableで実施)

コンストラクタで、HttpClientのインスタンスを生成して、getUsersメソッド内でAPIを実行。

URLは、前述で作成したLambda+API Gatewayのエンドポイント。

(要注意)HttpClientクラスをインスタンスかしたときにアベンドする

ここで1点ハマりどころがありましたので、要注意です。

実際にうごかく断面で判明したのですが、HttpClientクラスをインスタンス化するところでアベンドしてしまいます。

どうやらAngular17ではapp.config.tsで以下の対処が必要ということがわかりました。

/src/app/app.config.ts を以下のように編集。

import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';

import { provideHttpClient } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
  providers: [provideRouter(routes), provideHttpClient()]
};

providerHttpClientをインポートして、providersに追加します。

user-list.component.tsを編集

前述で中間確認用にオンコードでデータを記述していたところを、API連係に書き換えます。

/src/app/user-list/user-list.component.ts を以下のように編集。

import { Component } from '@angular/core';

import { User } from '../model/user.model';
import { NgFor } from '@angular/common';
import { UsersService } from '../api/users.service';

@Component({
  selector: 'app-user-list',
  standalone: true,
  imports: [NgFor],
  templateUrl: './user-list.component.html',
  styleUrl: './user-list.component.css'
})
export class UserListComponent {
  users: User[] = [];

  constructor(private service: UsersService) {}

  ngOnInit() {
    this.service.getUsers().subscribe((res:any) => {
      this.users = res.body.users;
    })
  }
}

UsersServiceをインポートして、コンストラクタでインスタンス化する。

初期処理(ライフサイクルフック)でAPI連係して、その結果をセットしています。

結果を確認

「ng serve --host 0.0.0.0」で実行し、ブラウザで見てみます。

しっかりとAPIの結果で画面が表示されていることが確認できました。

最後に

今回はObservableという方法で非同期処理を行いましたが、ReactのAxiosなんかだとPromiseで非同期をするのがスタンダードだと思います。
AngularでもPromiseでの方法もあるようなので、そこは今後の学習とします。

この記事までで、全4回に分けて、Angularの基本をまとめてみました。

実際のフロントエンド開発で、より深いところまで理解しながら進めていきたいと思います。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です