APIとデータベースをアプリに接続する
アプリケーションを作成および設定し、新しいAmplifyプロジェクトを初期化したので、機能を追加できます。最初に追加する機能はAPIです。
Amplify CLIはAPIカテゴリーの2つのタイプ、RESTとGraphQLの作成と相互作用をサポートしています。
このステップで作成するAPIは、AWS AppSync(マネージドGraphQLサービス)を使用するGraphQL APIであり、データベースはAmazon DynamoDB(NoSQLデータベース)になります。
GraphQL APIとデータベースを作成する
以下のコマンドを実行して、GraphQL APIをアプリに追加し、データベースを自動的にプロビジョニングします。アプリケーションディレクトリのルートから実行します:
amplify add api以下で強調されているデフォルト値を受け入れます:
? Select from one of the below mentioned services: GraphQL? Here is the GraphQL API that we will create. Select a setting to edit or continue Continue? Choose a schema template: Single object with fields (e.g., "Todo" with ID, name, description)CLIはこのGraphQLスキーマをテキストエディタで開くよう促します。
amplify/backend/api/your-api-name/schema.graphql
# This "input" configures a global authorization rule to enable public access to# all models in this schema. Learn more about authorization rules here: https://docs.amplify.aws/react/build-a-backend/graphqlapi/customize-authorization-rules/
input AMPLIFY { globalAuthRule: AuthRule = { allow: public }} # FOR TESTING ONLY!type Todo @model { id: ID! name: String! description: String}生成されたスキーマはTodoアプリ用です。Todoタイプの@modelディレクティブに気付くでしょう。このディレクティブはAmplify GraphQL APIカテゴリーの一部です。
Amplify GraphQL APIは、カスタムGraphQLディレクティブを提供し、データモデルを定義、認可ルールを設定、サーバーレス関数をリゾルバーとして構成するなど、さらに多くのことができます。
@modelディレクティブで装飾されたGraphQLタイプは、タイプ(Todoテーブル)のデータベーステーブル、CRUD(作成、読み取り、更新、削除)およびリスト操作のスキーマ、そしてすべてを一緒に機能させるために必要なGraphQLリゾルバーをスキャフォールディングします。
コマンドラインからEnterキーを押してスキーマを受け入れ、次のステップに進みます。
APIをデプロイする
このバックエンドをデプロイするには、pushコマンドを実行します:
amplify push各プロンプトに対して以下の値を選択します:
✔ Are you sure you want to continue? (Y/n) · yes...? Do you want to generate code for your newly created GraphQL API: Yes? Choose the code generation language target: typescript? Enter the file name pattern of graphql queries, mutations and subscriptions: src/graphql/**/*.ts? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions: Yes? Enter maximum statement depth [increase from default if your schema is deeply nested]: 2? Enter the file name for the generated code: src/API.ts✔ Are you sure you want to continue? (Y/n) · yes...? Do you want to generate code for your newly created GraphQL API Yes? Choose the code generation language target javascript? Enter the file name pattern of graphql queries, mutations and subscriptions src/graphql/**/*.js? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions Yes? Enter maximum statement depth [increase from default if your schema is deeply nested] 2? Enter the file name for the generated code src/API.jsAPIはライブになり、相互作用を開始できます。デプロイしたAPIには、投稿を作成、読み取り、更新、削除、および一覧表示するための操作が含まれています。
デプロイメントステータスを確認する
次に、以下のコマンドを実行してAmplifyのステータスを確認します:
amplify statusこれはAmplifyプロジェクトの現在のステータスを表示します。現在の環境、作成されたカテゴリー、およびそれらのカテゴリーの状態が含まれます。以下のようになります:
Current Environment: dev
┌──────────┬───────────────────────┬───────────┬───────────────────┐│ Category │ Resource name │ Operation │ Provider plugin │├──────────┼───────────────────────┼───────────┼───────────────────┤│ Api │ your-api-name │ No Change │ awscloudformation │└──────────┴───────────────────────┴───────────┴───────────────────┘AWSコンソールでデプロイされたAPIを確認する
AppSyncコンソールでGraphQL APIを任意の時点で表示するには、以下のコマンドを実行します:
amplify console apiAmplifyコンソールでアプリ全体を任意の時点で表示するには、以下のコマンドを実行します:
amplify consoleローカルモッキングでAPIをテストする
これをローカルでテストするには、mockコマンドを実行できます。注:モッキングをセットアップするための指示を参照してください。
フロントエンドを接続して先に進みたい場合は、次のステップにスキップできます。
amplify mock api注: amplify mock apiにはJavaが必要です。
# If you have not already deployed your API, you will be walked through the following steps for GraphQL code generation? Choose the code generation language target: javascript (or preferred target)? Enter the file name pattern of graphql queries, mutations and subscriptions: src/graphql/**/*.js? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions: Yes? Enter maximum statement depth [increase from default if your schema is deeply nested] 2これにより、ローカルポートでGraphiQLエクスプローラーが開きます。テスト環境から、クエリやミューテーションなど、さまざまな操作をローカルで試すことができます。
GraphiQLツールバーで、Use: User Poolを選択し、Todoを作成してみてください:
mutation CreateTodo { createTodo(input: { name: "Test Todo", description: "Todo description" }) { id owner name updatedAt createdAt description }}次に、認証をUse: API Keyに更新し、Todoのリストをクエリしてみてください:
query ListTodos { listTodos { items { description createdAt id owner name } }}フロントエンドをAPIに接続する
まず、todos Angular コンポーネントを作成します:
npx ng generate component --standalone todossrc/app/app.component.tsで、TodosComponentをインポートして Component imports に追加するように更新します:
import { Component } from '@angular/core';import { CommonModule } from '@angular/common';import { RouterOutlet } from '@angular/router';import { TodosComponent } from './todos/todos.component';
@Component({ selector: 'app-root', standalone: true, imports: [CommonModule, RouterOutlet, TodosComponent], templateUrl: './app.component.html', styleUrls: ['./app.component.css']})export class AppComponent { title = 'amplify-app';}src/app/app.component.htmlを開き、デフォルトのコンテンツを作成した Angular コンポーネントで置き換えます:
<app-todos></app-todos>src/app/todos/todos.component.tsファイルで、amplify add apiを実行したときに生成されたAPI.tsファイルを使用してミューテーションでデータベースにデータを追加します。さらに、必要なフォームヘルパーをインポートし、ReactiveFormsModuleを Component imports に追加してください:
import { Component } from '@angular/core';import { FormBuilder, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';import { generateClient, type Client } from 'aws-amplify/api';import { Todo, ListTodosQuery } from '../../API';import * as mutations from '../../graphql/mutations';
@Component({ standalone: true, imports: [ReactiveFormsModule], selector: 'app-todos', templateUrl: './todos.component.html', styleUrls: ['./todos.component.css']})export class TodosComponent { public createForm: FormGroup; public client: Client;
constructor(private fb: FormBuilder) { this.createForm = this.fb.group({ name: ['', Validators.required], description: ['', Validators.required] });
this.client = generateClient(); }
public async onCreate(todo: Todo) { try { const response = await this.client.graphql({ query: mutations.createTodo, variables: { input: todo } }); console.log('item created!', response); this.createForm.reset(); } catch (e) { console.log('error creating todo...', e); } }}次に、Todoを作成するために使用するフォームを追加します。src/app/todos/todos.component.htmlに以下を追加します:
<div class="form-body"> <form autocomplete="off" [formGroup]="createForm" (ngSubmit)="onCreate(createForm.value)" > <div> <label>Name: </label> <input type="text" formControlName="name" autocomplete="off" /> </div> <div> <label>Description: </label> <input type="text" formControlName="description" autocomplete="off" /> </div> <button type="submit">Submit</button> </form></div>次に、TodosComponentクラスを更新して、アプリが起動したときにデータベース内のすべてのTodoを一覧表示します。これを行うには、OnInitを実装し、src/app/todos/todos.component.tsにListTodosクエリを追加します。クエリ結果をアレイに保存します。
import { Component, OnInit } from '@angular/core';import { FormBuilder, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
import { generateClient, type Client } from 'aws-amplify/api';import { ListTodosQuery, Todo } from '../../API';import * as mutations from '../../graphql/mutations';import * as queries from '../../graphql/queries';
@Component({ standalone: true, selector: 'app-todos', imports: [ReactiveFormsModule], templateUrl: './todos.component.html', styleUrls: ['./todos.component.css']})export class TodosComponent implements OnInit { public createForm: FormGroup; public client: Client;
/* declare todos variable */ public todos: ListTodosQuery['listTodos'];
constructor(private fb: FormBuilder) { this.createForm = this.fb.group({ name: ['', Validators.required], description: ['', Validators.required] });
this.client = generateClient(); }
async ngOnInit() { /* fetch todos when app loads */ try { const response = await this.client.graphql({ query: queries.listTodos }); this.todos = response.data.listTodos; } catch (e) { console.log('error fetching todos', e); } }
public async onCreate(todo: Todo) { try { const response = await this.client.graphql({ query: mutations.createTodo, variables: { input: todo } }); console.log('item created!', response); this.createForm.reset(); } catch (e) { console.log('error creating todo...', e); } }}src/app/todos/todos.component.htmlに以下を追加して、追加したTodoを表示します:
<div> @for (todo of todos?.items; track todo?.id) { <div>{{ todo?.name }}</div> <div>{{ todo?.description }}</div> } @empty { <div>There are no items.</div> }</div>リアルタイムデータをサブスクライブするには、サブスクリプションクラス変数を宣言し、src/app/todos.component.tsでngOnInitを更新します。アプリが起動すると、このコードはサブスクリプションをセットアップします。サブスクリプションは新しいイベント(新しいTodoが作成されたとき)を受け取ったときにtodosアレイを更新します:
...
import * as subscriptions from '../../graphql/subscriptions'
export class TodosComponent implements OnInit {
private subscription: any = null;
...
async ngOnInit() {
...
try { const res = await this.client.graphql({ query: queries.listTodos }) console.log(res)
this.todos = res.data.listTodos.items; } catch(e) { console.log(e) };
/* subscribe to new todos being created */ this.subscription = this.client.graphql({ query: subscriptions.onCreateTodo }).subscribe({ next: (event: any) => { const newTodo = event.data.onCreateTodo; if(this.todos) { this.todos.items = [newTodo, ...this.todos.items]; } } }); }}最後に、コンポーネントが破棄されるときサブスクリプションを解除します。src/app/todos.component.tsでOnDestroyをインポートして追加します:
import { Component, OnDestroy, OnInit } from '@angular/core';
...
export class TodosComponent implements OnInit, OnDestroy {
...
ngOnDestroy() { if (this.subscription) { this.subscription.unsubscribe(); } this.subscription = null; }}最終的なtodos.component.tsファイルは以下のようになります:
import { Component, OnInit, OnDestroy } from '@angular/core';import { FormBuilder, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
import { generateClient, type Client } from 'aws-amplify/api';import { Todo, ListTodosQuery } from '../../API';import * as mutations from '../../graphql/mutations';import * as queries from '../../graphql/queries';import * as subscriptions from '../../graphql/subscriptions';
@Component({ standalone: true, selector: 'app-todos', imports: [ReactiveFormsModule], templateUrl: './todos.component.html', styleUrls: ['./todos.component.css']})export class TodosComponent implements OnInit, OnDestroy { public todos: ListTodosQuery['listTodos']; public createForm: FormGroup; public client: Client;
private subscription: any = null;
constructor(private fb: FormBuilder) { this.createForm = this.fb.group({ name: ['', Validators.required], description: ['', Validators.required] });
this.client = generateClient(); }
async ngOnInit() { /* fetch todos when app loads */ try { const response = await this.client.graphql({ query: queries.listTodos }); this.todos = response.data.listTodos; } catch (e) { console.log('error fetching todos', e); }
this.subscription = this.client .graphql({ query: subscriptions.onCreateTodo }) .subscribe({ next: (event: any) => { const newTodo: Todo = event.data.onCreateTodo; if (this.todos) { this.todos.items = [newTodo, ...this.todos.items]; } } }); }
ngOnDestroy(): void { if (this.subscription) { this.subscription.unsubscribe(); } this.subscription = null; }
public async onCreate(todo: Todo) { try { const response = await this.client.graphql({ query: mutations.createTodo, variables: { input: todo } }); console.log('item created!', response); this.createForm.reset(); } catch (e) { console.log('error creating todo...', e); } }}ローカルで実行する
次に、アプリを実行して、Todoを作成および表示する機能を備えた更新されたUIが表示されることを確認します:
npm startAPIを正常にデプロイし、アプリに接続しました。