中安拓也のブログ

プログラミングについて書くブログ

【Angular + Firebase】ログイン中のアカウントの情報を表示する

f:id:l08084:20200606211323p:plain
ログイン中のアカウントの情報を表示している

はじめに

ログインしているアカウントのサムネイル画像とアカウント名を表示する機能を実装します。

環境

フロントサイドのフレームワークとしてAngularを、バックエンドにFirebaseを使用しています。CSSフレームワークはAngular Materialです。

  • Angular CLI@8.3.20
  • Node@12.13.1
  • Angular@8.2.14
  • firebase@6.3.4
  • angular/fire@5.2.1

ログイン中のアカウントの情報を表示する

それでは、ヘッダー上にログイン中のアカウントの情報を表示する機能を実装していきます。

認証のサービスクラスを作成する

まず、ログインしているアカウントの情報を取得するため、認証関連の処理をまとめたサービスクラスであるAuthenticationServiceを作成します。

authentication.service.ts

import { Injectable } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';
import { Observable } from 'rxjs';
import { User } from 'firebase';

/**
 * 認証関連のサービスクラス
 *
 * @export
 * @class AuthenticationService
 */
@Injectable({
  providedIn: 'root'
})
export class AuthenticationService {
  constructor(public afAuth: AngularFireAuth) {}

  /**
   * ログインしているアカウントの情報を返す
   *
   * @returns {User}
   * @memberof AuthenticationService
   */
  public getCurrentUser(): User {
    return this.afAuth.auth.currentUser;
  }

  /**
   * ログアウトする
   *
   * @returns {Promise<void>}
   * @memberof AuthenticationService
   */
  public signOut(): Promise<void> {
    return this.afAuth.auth.signOut();
  }

  /**
   * ログインしているアカウントの情報を返す
   *
   * @returns {Observable<User>}
   * @memberof AuthenticationService
   */
  public getUser(): Observable<User> {
    return this.afAuth.user;
  }
}

AuthenticationServiceは、ログインしているアカウントの情報を返すメソッドや、ログアウトするメソッドを持っています。

ヘッダーにアカウントの情報を表示する

HTMLテンプレート

ヘッダー上でアカウントの情報を表示している部分のテンプレート(HTML)について説明します。

header.component.html

<!-- ログインアカウント情報(ログインしている時のみ表示される) -->
<!-- ログインしているアカウントの情報を表示したい -->
<div class="right-icon" *ngIf="authenticationService.getUser() | async">
  <button mat-button class="account-link" [matMenuTriggerFor]="menu">
    <img class="thumbnail" *ngIf="currentUser.photoURL" src="{{currentUser.photoURL}}" />
    {{currentUser.displayName}}<mat-icon>expand_more
    </mat-icon>
  </button>
  <!-- Angular Materialのメニューを使用している -->
  <mat-menu #menu="matMenu">
    <button mat-menu-item (click)="signOut()">
      <mat-icon>exit_to_app</mat-icon>ログアウト
    </button>
  </mat-menu>
</div>

*ngIf="authenticationService.getUser() | async"と書くことでログイン時のみ(アカウントが存在する時のみ)にヘッダー上にアカウントの情報を表示することができます。

また、photoURLプロパティとdisplayNameを表示することでアカウントのサムネイル画像とアカウント名を表示しているのと、Angular MaterialのMenuを使用することで、アカウント名をクリックするとメニューでログアウトボタンを表示する仕様になっています。

コンポーネントクラス

コンポーネントクラスではAuthenticationServiceを呼び出すことで、ログアウト、アカウント情報の取得処理を実装しています。

header.component.ts

import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core';
import { SpinnerService } from 'src/app/services/spinner.service';
import { Router } from '@angular/router';
import { ToastService } from '../../services/toast.service';
import { AuthenticationService } from 'src/app/services/authentication.service';
import { Observable } from 'rxjs';

/**
 * 画面ヘッダーのコンポーネントクラス
 *
 * @export
 * @class HeaderComponent
 * @implements {OnInit}
 */
@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {
  @Input() isHandset$: Observable<boolean>;
  @Output() drawerToggled = new EventEmitter<void>();

  public currentUser: firebase.User;

  constructor(
    private router: Router,
    private _toastService: ToastService,
    private authenticationService: AuthenticationService,
    private spinnerService: SpinnerService
  ) {}

  ngOnInit() {
    this.retrieveUserProfile();
  }

  /**
   * ログアウト処理
   *
   * @memberof HeaderComponent
   */
  public async signOut() {
    // スピナー表示
    this.spinnerService.show();
    // ログアウトAPIを呼び出す
    try {
      await this.authenticationService.signOut();
      // ログアウトが成功したら、ログイン画面に遷移
      this.router.navigate(['/login']);
      this._toastService.open('ログアウトしました。');
    } catch (error) {
      this._toastService.open('ログアウトに失敗しました。');
      console.log(error);
    } finally {
      this.spinnerService.hide();
    }
  }

  /**
   * ログインしているユーザーの情報を取得する
   *
   * @private
   * @memberof HeaderComponent
   */
  private retrieveUserProfile() {
    this.currentUser = this.authenticationService.getCurrentUser();
  }
}

header.component.scss

.right-icon {
  align-items: baseline;
  cursor: pointer;
  display: flex;
  margin: 0 0 0 auto;

  .thumbnail {
    border-radius: 12px;
    width: 24px;
    height: 24px;
  }
}

上記のようにコードを書くと、ヘッダーにアカウントの情報を表示することができるようになります。

f:id:l08084:20200607185126p:plain
Twitterでログインした場合の表示例

参考サイト

Firebase でユーザーを管理する