AWS Amplify+Angular6+Cognitoでログインページを作ってみる ~UI編~

本ブログではAWS Amplify+Angular6+Cognitoでログインページを作っていきます。また、ついでに、API GatewayにもCognitoで認証をかけて、Cognitoでログインしているユーザのみ利用できるようにしていきます。
2018.06.21

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

どうも!大阪オフィスの西村祐二です。

本ブログは下記の続きになります。今回が最終回となります。

AWS Amplify+Angular6+Cognitoでログインページを作ってみる ~フロントエンド編②~

ゴールとして下記動画のようなサイトを構築していきます。

前回は、画面を構成するコンポーネントの実装を行いました。

今回は、そのコンポーネントに対して、Bootstrap4でスタイリングをしていきます。 Bootstrapを使うことでCSSを記述することなく、配置の設定や、スタイリングをすることができます。

ログイン画面

LoginComponent

ログイン画面のコンポーネントに対してスタイリングしていきます。

login.component.html

<div class="card text-center w-50 mx-auto">
  <div class="card-header">
    サンプルログインサイト
  </div>
  <div class="card-body">
    <form [formGroup]="loginForm" (ngSubmit)="onSubmitLogin(loginForm.value)">
      <div class="form-group text-left">
        <label>メールアドレス</label>
        <input type="email" class="form-control" placeholder="Enter email" formControlName="email">
      </div>
      <div class="form-group text-left">
        <label>パスワード</label>
        <input type="password" class="form-control" placeholder="Password" formControlName="password">
      </div>
      <button type="submit" class="btn btn-primary">ログイン</button>
    </form>
  </div>
</div>

▼スタイリング・レイアウト

▼コンポーネントとの連携

  • [formGroup]="loginForm"
  • ここで設定されてるフォームタグをlogin.component.tsで設定しているloginFormとを紐づけしています。

  • (ngSubmit)="onSubmitLogin(loginForm.value)"

  • submitされてとき、login.component.tsで設定されてるonSubmitLogin(loginForm.value)が実行され、引数にloginFormの値がわたされます。

  • formControlName="email"、formControlName="password"

  • フォームとlogin.component.tsで設定しているloginForm内の値を取得するためのフォーム名と紐づけします。

https://dev.classmethod.jp/cloud/aws/aws-amplify-angular6-cognito-loginpage-frontend-2#toc-

サインアップ画面

SignupComponent

サインアップ(登録)画面のコンポーネントに対してスタイリングします。 このページでは、登録情報の入力と、確認コードの検証を行います。

signup.component.html

<div class="card text-center w-50 mx-auto">
  <div class="card-header">
    サインアップ
  </div>
  <div class="card-body">

    <div class="signup" *ngIf="!successfullySignup">
      <form [formGroup]="signupForm" (ngSubmit)="onSubmitSignup(signupForm.value)">

        <div class="form-group text-left">
          <label>メールアドレス</label>
          <input type="email" class="form-control" placeholder="Enter email" formControlName="email">
        </div>
        <div class="form-group text-left">
          <label>パスワード</label>
          <input type="password" class="form-control" placeholder="Password" formControlName="password">
        </div>
        <button type="submit" class="btn btn-primary">登録</button>
      </form>
    </div>

    <p class="mt-5" *ngIf="!successfullySignup">検証コードを入力する場合はこちら</p>
    <button (click)="successfullySignup = true" *ngIf="!successfullySignup" class="btn btn-secondary">検証コードで認証</button>

    <div class="confirmation" *ngIf="successfullySignup">
      <form [formGroup]="confirmationForm" (ngSubmit)="onSubmitConfirmation(confirmationForm.value)">
        <div class="form-group text-left">
          <label>メールアドレス</label>
          <input type="email" class="form-control" placeholder="Enter email" formControlName="email">
        </div>


        <div class="form-group text-left">
          <label>検証コード</label>
          <input type="email" class="form-control" placeholder="Enter confirmationCode" formControlName="confirmationCode">
        </div>
        <button type="submit" class="my-3 btn btn-primary">認証</button>
      </form>
      <button (click)="successfullySignup = false" class="btn btn-secondary">もどる</button>
    </div>

  </div>
</div>

▼スタイリング・レイアウト

基本的にログイン画面と同じなので、そちらを参照ください。

▼コンポーネントと連携

https://dev.classmethod.jp/cloud/aws/aws-amplify-angular6-cognito-loginpage-frontend-2#toc-1

  • div class="signup" *ngIf="!successfullySignup">
  • successfullySignupFalseのときにdivが囲まれたタグが表示されます。

  • 「検証コードで認証」ボタン

  • ここをクリックするとsuccessfullySignupTrueになり、上のdivタグが非表示なります。これでDOMの切り替えを行います。

ペット情報取得、一覧表示画面

PetComponent

ペット情報取得、一覧表示画面を作成します。 このページでは、APIを叩いてペット情報を取得、取得した情報を画面に表示します。

pet.component.html

<button (click)="Pet()" class="btn btn-success mx-3 my-3">情報取得リクエスト</button>

<div class="main" *ngIf="petsData">
  <h2 class="list-title">ペット情報</h2>

  <div class="table-responsive">
    <table class="table table-sm table-bordered table-hover">
      <thead>
        <tr>
          <th>#</th>
          <th>id</th>
          <th>type</th>
          <th>price</th>
        </tr>
      </thead>
      <tbody>
        <ng-container *ngFor="let pet of petsData; index as i;">
          <tr>
            <td>{{i+1}}</td>
            <td>{{pet.id}}</td>
            <td>{{pet.type}}</td>
            <td>{{pet.price}}</td>
          </tr>
        </ng-container>
      </tbody>
    </table>
  </div>
</div>

▼スタイリング・レイアウト

▼コンポーネントとの連携

https://dev.classmethod.jp/cloud/aws/aws-amplify-angular6-cognito-loginpage-frontend-2#toc-2

  • *ngIf="petsData
  • 「情報取得リクエスト」ボタンクリック時に取得した値が格納されるまで、非表示のままで、値が格納されたら、petsDataTrue判定になるので、テーブルが表示されます。

  • ng-container *ngFor="let pet of petsData; index as i;">

  • ng-containerngForを使うためのダミーのコンテナー要素になります。
  • for文について、petsData内の要素を取り出し、petに繰り返し格納していきます。
  • index as iはfor文などで繰り返し行われる処理の回数を数えるときに便利な機能です。iに回数が格納されていきます。

ホーム画面

HomeComponent

ログイン済みのユーザーのみが閲覧出来るページのコンポーネントを作成します。

home.component.html

<p class="username">
  ようこそ! {{username}}
</p>
<app-pet></app-pet>

ナビバー

AppComponent

AppComponentには各ページ共通で表示するナビゲーションを配置しました。

<nav class="navbar navbar-expand-sm navbar-light bg-light mb-5">
  <a class="navbar-brand" [routerLink]="['/']">ホーム</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarText" aria-controls="navbarText"
    aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarText">
    <ul class="navbar-nav mr-auto">
      <li class="nav-item" *ngIf="!(auth.loggedIn | async)">
        <a class="nav-link" [routerLink]="['/login']">ログイン
        </a>
      </li>
      <li class="nav-item">
        <a class="nav-link" (click)="onClickLogout()">ログアウト</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" [routerLink]="['/signup']">登録</a>
      </li>
    </ul>
    <span class="navbar-text">
      {{username}}
    </span>
  </div>
</nav>


<div class="container">
  <router-outlet></router-outlet>
</div>

▼スタイリング・レイアウト

▼コンポーネントとの連携

https://dev.classmethod.jp/cloud/aws/aws-amplify-angular6-cognito-loginpage-frontend-2#toc-4

  • *ngIf="!(auth.loggedIn | async)"
  • コンポーネントで保持しているauth.loggedInの値がFalseのとき表示されます。また、asyncの設定をすることで非同期で値を取得します。これによって、ログイン時にログインのリンクを非表示にしています。

styles.css

/* フォーカスした時の枠線を消す */
*:focus {
 box-shadow:none !important;
}

chromeでテキスト入力欄などにフォーカスしたとき付与されるスタイルがとても違和感にかんじたので、無効化しています。

以上で全部の実装完了です。

動作確認

ローカルサーバを起動して確認します。

$ ng serve --open

さいごに

いかがだったでしょうか。

Bootstrap4を使ってスタイリングをやってみました。CSSを書くことなくマージンやパッディング、配置などの設定が行えるのでとても便利です。

長くなりましたが、今回で最終回となります。

誰かの参考になれば幸いです。