【Angular v19 + SpringBoot 05】Angular側のAPI連携

【スキル】エンジニア
たけ坊
たけ坊

バックエンドからデータを取得するための準備を進めていくよ!

フロントエンドとバックエンドの連携ができるんですね!

たけ坊
たけ坊

バックエンドはいったんおいて、フロントエンドの内容を進めるよ!

前提

これまでの流れを知りたい人はこちら!

APIを呼び出す

APIについてはこちらから

APIとは何か? API連携ってどういうこと? 図解で仕組みをやさしく解説
インターネット上で提供されている企業のWebサービスを見ると、必ずと言っていいほど、どこかに「API」という単語が見つかるはずです。しかし、APIとは、あるいはAPI連携とは具体的にどのような仕組みのことを言っているのでしょうか? 本稿では...

まずは下ごしらえ。/shared/modelsにpain-data-log-entity.tsを作成します。

ng-pain-log/
└── pain-log/
    └── src/
        └── app/
            ├── core/
            ├── domain/
            ├── features/
            ├── infrastructures/
            ├── shared/
            │   └── models/
            │       └── pain-data-log-entity.ts
            ├── app.component.html
            ├── app.component.ts
            ├── app.component.less
            └── app.routes.ts

そして、以下のようにテーブルに表示させるデータの型を作成しておきます。

export interface PainLogResultDataEntity {
    id: number;
    date: Date;
    name: string;
    movement: string;
    vas: number;
    memo: string;
}

次に、APIを呼び出す場所をinfrastructures以下に作成します。参考のコマンドは、

ng generate service api

です。これを実行すると、

ng-pain-log/
└── pain-log/
    └── src/
        └── app/
            ├── core/
            ├── domain/
            ├── features/
            ├── infrastructures/
            │   └── services/
            │       └── api.service.ts
            ├── shared/
            ├── app.component.html
            ├── app.component.ts
            ├── app.component.less
            └── app.routes.ts

api.service.tsが作成されます。

API呼び出し先であるバックエンドは後で作成するのでお待ちくださいね!

api.service.tsは以下のような中身になります。

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { PainLogResultDataEntity } from '../../shared/models/pain-log-data-entity';

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

  private url = "http://localhost:8081"

  constructor( private http: HttpClient ) { }

  insertPatients(patient: PainLogResultDataEntity): Observable<PainLogResultDataEntity> {
    return this.http.post<PainLogResultDataEntity>(`${this.url}/insert`, patient);
  }

  selectPatients(): Observable<PainLogResultDataEntity[]> {
    return this.http.get<PainLogResultDataEntity[]>(`${this.url}/select`);
  }

  searchPatients(user: string, movement: string): Observable<PainLogResultDataEntity[]> {
    return this.http.get<PainLogResultDataEntity[]>(`${this.url}/search?user=${user}&movement=${movement}`);
  }

  updatePatients(patient: PainLogResultDataEntity): Observable<PainLogResultDataEntity> {
    return this.http.put<PainLogResultDataEntity>(`${this.url}/update`, patient);
  }

  deletePatients(id: number): Observable<void> {
    return this.http.put<void>(`${this.url}/delete`, id);
  }

}

APIの呼び出しを作成する際のキーワードとして “CRUD” とい言葉が出てきます。
・Create
・Read
・Update
・Delete
の略です。これらに関するAPIを作成することがポイントです。

CreateはInsert、ReadはSelectという言葉に代わっていますが、意味はほぼ同じです。

上記のAPIの書き方は以下を参考にしました。

Angular入門:APIのとのやり取り - Qiita
AngularはSPAのフレームワークなので動的処理は基本的にサーバ側APIとのやり取りになります。ここでは簡単なCRUD処理を試してみます。簡単なAPIサーバの実装まず、expressを利用…

これを作成したら、このapi.service.tsをどのように活用するのかを見ていきます。

ng-pain-log/
└── pain-log/
    └── src/
        └── app/
            ├── core/
            ├── domain/
            ├── features/
            │   └── pages/
            │       └── dashboard/
            │           ├── dashboard.component.html
            │           ├── dashboard.component.ts
            │           └── dashboard.component.less
            ├── infrastructures/
            ├── shared/
            ├── app.component.html
            ├── app.component.ts
            ├── app.component.less
            └── app.routes.ts

dashboard.component.tsを下記のように変更します。

import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import {MatTableModule} from '@angular/material/table';
import { PainLogResultDataEntity } from '../../../shared/models/pain-log-data-entity';
import { ApiService } from '../../../infrastructures/services/api.service';
import { HttpClientModule } from '@angular/common/http';

const painLog: PainLogResultDataEntity[] = [];

@Component({
  selector: 'app-dashboard',
  standalone: true,
  imports: [CommonModule, MatTableModule, HttpClientModule],
  templateUrl: './dashboard.component.html',
  styleUrl: './dashboard.component.less'
})

export class DashboardComponent {
  displayedColumns: string[] = ['date', 'name', 'movement', 'vas', 'memo'];
  dataSource: PainLogResultDataEntity[] = [];

  constructor(private service: ApiService) {
    this.service.selectPatients().subscribe(data => {
      this.dataSource = data;
    });
  }
}

参考は以下のサイトですが、少し異なる点としてthenではなく、subscribeを利用してデータを取得しています。

Angular Mat Table With API Call - StackBlitz
Basic use of <table mat-table>

dashboard.component.tsに合わせて、dashboard.componen.htmlも変更しましょう。

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">

  <!-- Date Column -->
  <ng-container matColumnDef="date">
    <th mat-header-cell *matHeaderCellDef> Date </th>
    <td mat-cell *matCellDef="let element"> {{element.date}} </td>
  </ng-container>

  <!-- Name Column -->
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef> Name </th>
    <td mat-cell *matCellDef="let element"> {{element.name}} </td>
  </ng-container>

  <!-- Movement Column -->
  <ng-container matColumnDef="movement">
    <th mat-header-cell *matHeaderCellDef> Movement </th>
    <td mat-cell *matCellDef="let element"> {{element.movement}} </td>
  </ng-container>

  <!-- VAS Column -->
  <ng-container matColumnDef="vas">
    <th mat-header-cell *matHeaderCellDef> VAS </th>
    <td mat-cell *matCellDef="let element"> {{element.vas}} </td>
  </ng-container>

  <!-- Memo Column -->
  <ng-container matColumnDef="memo">
    <th mat-header-cell *matHeaderCellDef> Memo </th>
    <td mat-cell *matCellDef="let element"> {{element.memo}} </td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

ここまで変更して、

ng serve

または

npx ng serve --host 0.0.0.0 --poll 1

を実行してみますが、私の場合はheaderがおかしくなってしまいました。

原因を調べると、main.tsにHttpClientModuleが入っていないことのようなので、

ng-pain-log/
└── pain-log/
    └── src/
        ├── app/
        └── main.ts
import { enableProdMode, importProvidersFrom } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { provideRouter } from '@angular/router';
import { AppComponent } from './app/app.component';
import { routes } from './app/app.routes';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { HttpClientModule } from '@angular/common/http';


bootstrapApplication(AppComponent, {
  providers: [provideRouter(routes), provideAnimationsAsync(), importProvidersFrom(HttpClientModule)],
}).catch((err) => console.error(err));

上記のように直すと…

無事にweb上に表示されました!

※headerの色は変えてみました。自分で調べて変えてみてね!

次のステップ

次はバックエンドの実装に入っていきます!

タイトルとURLをコピーしました