Angular5+Firebaseでチャットアプリを作る④ 新規ユーザー登録編

この記事は次の記事の続きです。

Angular5+Firebaseでチャットアプリを作る③ 編集・削除編

また、この記事は次の教材を参考に作成しています。おすすめの教材です。

この教材がないと細々としたところはわからないと思います。

参考:【最新v5対応】はじめてのAngular入門 実践シングルページアプリケーション(SPA)構築 | Udemy

前回は、編集と削除の機能を実装しました。また、アイコンや編集画面も併せて作成しました。

今回は、一つのコンポーネントに機能をすべて詰め込んでいるので分散させて拡張性を高めて、今後の開発をしやすくしていきます。

さらに、Angularで新規ユーザー登録機能を実装して、Firebase認証設定をおこない、サインアップ機能を実装していきたいと思います。

では、その前に今後実装する機能について確認していきましょう。

実装予定の機能

  • チャット初期画面
  • 認証機能(ログイン、ログアウト)
  • アカウント新規作成

等々、増やしたい機能があります。

今のコンポーネントで一杯一杯なコード量なのでこれ以上増やすと機能の拡張をしづらくなってしまいます。

そこでコンポーネントを幾つか分けて機能の分散を試みます。

コンポーネントの分散

まずチャット機能を別のコンポーネントに移します。

次のコマンドを実行します。

コマンド  ng g component chat

このchatコンポーネントに今まで作ってきたコンポーネントを移します。

importやconstとクラス内を移動します。

そして、importの参照パスの変更と、コンストラクター内の定義をngOnInit()に移します。

ただし、commentsRefの定義はコンストラクター内に残します。

commentsRefは変数ではなく定数なのでコンストラクターで定義してしまいます。

そしてこれまでのコンポーネントには不要なものは全て消して、htmlとcssの移しも行います。切り取りコピペでかまいません。

そして、app.component.htmlに次のコードを入れればこれまで通り動きます。

<app-chat></app-chat>

app.component.tsをシンプルに保つのが実装に最適となります。

@NgModule

コンポーネントやパイプやサービスなどをひとまとまりにする機能が@NgModuleです。

今はapp.module.tsでひとまとまりにしています。

これらを機能ごとに分けて拡張性を高めたいと思います。

Angularのスタイルガイドでは4つにモジュールを分けることを推奨しています。
  • ルートモジュール
    • アプリケーションの起動に使います
    • app.module.ts
    • BrowserModuleを読み込む
  • 機能モジュール
    • 機能ごとにコンポーネントやサービスをまとめるモジュール
  • 共有モジュール
    • サイト全体で使う共通のサービスをまとめるモジュール
  • コアモジュール
    • サイトに一つしか必要ないものをまとめておくためのモジュール
    • サイトヘッダーなど

これらを作っていきます。

共有モジュール

まず共有モジュールから作っていきます。

次のコマンドを実行します。

コマンド ng g module sharde

作成したshardeモジュールを開くとCommonModuleがインポートされています。

import { CommonModule } from ‘@angular/common’;

これは、NgIfやNgForの機能を持つBrowserModuleとほど同じ役割を持ちます。

ただし、BrowserModuleはアプリに必要なサービスをプロバイドするため、ルートモジュールでのみインポートすべきモジュールです。

そのため、このルートモジュール以外ではCommonModuleがインポートされています。

参考:NgModule FAQs – Qiita

さらに、app.module.tsから共有部分をshardeモジュールに移します。

import { FormsModule } from ‘@angular/forms’;
import { CommentDatePipe } from ‘../pipe/comment-date.pipe’;

共有部分とはどこからでもアクセスしたいデコレーションやパイプなどがそれに当たります。

@NgModuleのインポートに書き加えるのを忘れずに。

さらに@NgModule内に新たにexports: []を追加します。

これは共有モジュールが他のモジュールでインポートされれば、共有モジュールのexportsを自動的に読み込むので、exports[]にあれるモジュールは改めてインポートする必要がなくなります。

exportsにここで読み込んでいるすべてを追加します。

そしてapp.module.tsに次のインポートを追加しましょう。

import { SharedModule } from ‘./shared/shared.module’;

これでapp.moduleでSharedModuleのexportsが使うことができるようになりました。

コアモジュール

同じようにコアモジュールを作っていきます。

コマンド ng g module core

まず、app.module内に次のコードを追加しましょう。

import { CoreModule } from ‘./core/core.module’;

では、コアモジュールを開き編集していきます。

ここにはサイトに一つしか無いものを加えます。

インポートの{ NgModule }の中にOptional, SkipSelfを加えます。

さらに、クラス内にコンストラクターとして次のコードを定義します。

これで、二重に読み込まれるのを防ぐようになりました。

この記述はAngular公式を参考にしています。Angular – Style Guide

どうして、これで二重読み込みさせないのかはわかりませんでしたm(_ _)m

ヘッダーを作る

さて、今回はヘッダーをここに追加するので次のコマンドを入力します。

コマンド ng g component core/header

これをコアモジュールの@NgModule.exports[]内に追加します。

では、app.component.htmlの先頭に<app-header></app-header>を追加し、ヘッダーテンプレートに次のコードに書き換えます。

また、cssはこちらです。

.navbar {
border-bottom: 1px solid #ddd;
}
ヘッダーの構造

ヘッダーの構造を見ていきましょう!

サーバーを実行すればこのように表示されることになります。

そして今、ヘッダーを追加したわけですが、短いコードを追加した割にはしっかりとしたヘッダーができています。

これもBootstrapのおかげです。

  • navbar:最も基本的なBootstrapのヘッダーのスタイル。これだけでもシンプルだが見た目は良い。
  • justify-content-between:子要素を両揃えで並べる(Bootstrap
  • fixed-top:画面の上部に固定
  • navbar-inverse:色を指定します(Bootstrap)
  • bg-light text-dark:バックグラウンドは白でテキストは黒(Bootstrap)
  • navbar-brand:サイト名に利用する装飾(Bootstrap)
  • navbar-text:ナビゲーションバー用テキスト装飾(Bootstrap)

これらのスタイルを簡単に使うことでスッキリしたヘッダーが簡単にできます。

さて、これで共有モジュールとコアモジュールを作ることができました。

次は、ルートモジュールと機能モジュールに取り掛かりたいところですが、一旦置いておいて、ログインページの作成やルーティングの設定からしていきます。

ルーティングを設定する

では、ルーティングを設定していきましょう。

ここはほとんど次のtutorialのおさらいです。

[超初心者が行く]ルーティング編 Angular5 Tutorialしてみた7 – まんくつ

次のコマンドを実行します。

コマンド ng g module app-routing –flat –module=app
  • –flat:ディレクトリを作らずルートにファイルを作成します
  • –module=app:app.module.tsにルーティングモジュールを読み込ませます。自動的にapp-routingがapp.module.tsインポートと@NgModuleに追加されます。

そして、ルートを指定するためにインポートとRoutesを定義します。

import { RouterModule, Routes } from ‘@angular/router’;
import { ChatComponent } from ‘./chat/chat.component’;
const routes: Routes = [
{ path: ”, component: ChatComponent },
];

チャットコンポーネントがルートパスになります。

さらに、次のようにexportsを指定して、app.module.tsに読み込ませます。

exports: [RouterModule],

@NgModule.importsRouterModule.forRoot(routes) を入れるのを忘れずに。

このコードでルートモジュールにRoutesとして定義したパスを渡し、ルーティング設定をおこないます。

エラーページ作成

次に、存在しないページにアクセスした際のエラーページを作成しましょう。

次のコマンドを実行します。

コマンド ng g component error/not-found

教材からhtmlとcssをコピペします。

not-found.component.html

not-found.component.css

では、app-routingを開き次のコードを追加します。

import { NotFoundComponent } from ‘./error/not-found/not-found.component’;

それとRoutesに

{ path: ‘**’, component: NotFoundComponent }

この二つのコードを追加します。

  • ‘**’:指定したパス以外を網羅したワイルドカードです。Routesは上から評価するので一番下で指定しましょう。

Routes指定していないパスは全てエラーコンポーネントにアクセスします。

これでエラーページが実装できました。

htmlの構造

では、htmlを見ていきましょう。

最初の要素でcardクラスを指定して子要素を一枚のカードのように表示させています。

これはBootstrapの機能です。ですが、カードの装飾自体はcssで指定しています。

次の要素のcard text-centerで子要素をカードの中央に表示するようにしています。

これもBootstrapの機能です。

次の要素のcard-blockでカードにする要素を指定し、「404 ページが見つかりません」がカードとして表示されるようになります。

シンプルですが使い勝手の良いエラーページになっています。

ユーザー新規登録機能

ざっと、機能分散ができたところで、ルーティングも含めて、ユーザー登録機能を実装してみたいと思います。

ユーサー作成

ユーザー作成機能を追加していきます。

次のコマンドを実行します。

コマンド ng g component sign-up

教材からhtmlとcssをコピペします。

sign-up.component.html

sign-up.component.css

では、エラーページと同じようにルーティング設定していきます。

では、app-routingを開き次のコードを追加します。

import { SignUpComponent } from ‘./sign-up/sign-up.component’;

それとRoutesのエラーパスの上に、

{ path: ‘signup’, component: SignUpComponent },

を追加します。

これで、http://localhost:4200/signupにアクセスするとサインアップページが開くようになりました。

ここで、signupへの導線がないのでヘッダーをloginからsignupに変更して、hrefをrouterLinkに変更します。

href=”#” → routerLink=”/signup”

また、上のホームアクセスも次のように変えます。

routerLink=”/”

そして、coreモジュールでもappモジュールのようにAppRoutingModuleをインポートすればルーター設定がヘッダーでも効くようになります。

実際にページ遷移できるか確認してみてください。

ユーザー認証機能

次にユーザー認証機能を実装していきます。

ユーザー作成サービス

次のコマンドを実行しましょう。

コマンド ng g service core/service/auth

サービスを使う理由としては、コンポーネントでデータを保存するのが推奨されていないからです。

データベースに値の保存をさせる機能はサービスを使うことが推奨されています。

では、作成したサービスで認証にかかわる定義をしていきます。

auth.service.ts

  • create():emailとpasswordを受け取ってAngularFireAuthというFirebase認証機能のcreateUserWithEmailAndPasswordというユーザー作成メソッドを使ってユーザーを新規作成します。
  • auth$:ObservableをSubjectによってauthを任意のタイミングで実行します。今回は新規作成ボタンがクリックしされ、createが実行された時にストリームから入力値を受け取れるようにします。
  • then():アカウントを作成したらルートパスに戻るようにします。

Subjectの使い方がややこしいですが、今回のようにObservableを扱い、subscribeではなく任意のタイミングで値を取得したいときはSubjectをこのように記述し、使用ます。

newでObservableを初期化して任意のタイミングで値を正確に取得します。

サービスを追加したらコアモジュールにインポートするのを忘れずに。

追加したサービスを機能させる sign-up.component.htmlのクリックイベントは次のコードです。

f=”ngForm” (ngSubmit)=”signup(f)”

そして、inputタグ内のngModelです。

これは今まで[(ngModel)]としてクリックイベントで入力値を受け取る時に使ってきましたが、今回はとくに括弧は付けずにこのままで機能します。

今回はその代わりと言ってはなんですが、(Click)のように(ngSubmit)に括弧がつきます。

これはフォームタグ内のtype=”submit”のボタンのクリックイベントに反応し、ngModelを持つinputタグ内の入力値を配列に組込みます。

例えば、はじめのinputタグの入力値は、name=”email”なのでf.value.nameに格納されます。

これで入力値をデータベースに受け渡す機能が完成しました。

と、その前に、サービスに入力値を受け渡す機能を実装しましよう。

sign-up.component.tsに幾つかコードを追加していきます。

constructorにサービスを定義し、

private authService: AuthService

クラス内に、signup()を加えます。

signup(f: NgForm): void {
this.authService.create(f.value.email, f.value.password);
}

これで、入力値がサービスに受け渡されるようになりました。

適宜、インポートも忘れずに。

Firebase認証設定

さて、一通り認証機能を実装しました。

ただし、まだ終わりではありません。

Firebase側でメールアドレスでログインできるように設定していきましょう。

まず、Firebaseを開きます。

Firebase console

以前作成したプロジェクを開きコンソール画面を開きます。

プロジェクト作成方法はこちら:Angular5+Firebaseでチャットアプリを作る② Firebase連携編 – まんくつ

コンソール画面まで進み、Authentication(認証)を開きます。

次にログイン方法を指定していきます。

今回はメールをログイン情報とするので、メール/パスワードの設定をします。

メール/パスワードの右端の編集アイコンをクリックします。

有効にして、保存をクリックします。

メール/パスワードが有効になりました。

これで、メールとパスワードでログインできるようになりました。

一度、実行中のAngular ChatアプリのSign Inをクリックし、必要事項を入力し、登録してみましょう。

Firebaseでログイン方法を指定した、画面左上Authentication真下の、「ユーザー」タグを開くと登録したメールアドレスが追加されているはずです。

これでアプリからユーザーを登録できるようになりました。

次回はログイン・ログアウト

とりあえず今回は目的の機能分散とユーザー登録まで終わったのでここまでにします。

次回はログイン・ログアウト機能を実装させていきます。

段々とアプリ完成が見えてきました。