LoginSignup
80
46

More than 3 years have passed since last update.

AngularのプロジェクトにFirebaseを導入する

Last updated at Posted at 2017-06-08

この記事はAngular+Firebaseでチャットアプリを作るのエントリーです。
前記事:Firebaseの環境構築
次記事:Angular+Cloud Firestore(CREATE, READ, UPDATE, DELETE)を実装する

この記事で行うこと

本稿では、Angularのプロジェクトに「angularfire」というライブラリを使ってFirebaseの導入を行います。

angularfireとは

Angularで使い勝手がよくなるようラッピングされた、Firebaseクライアントです。
RxJSを使ってクライアントとFirebase間の同期を行うのが特徴で、現在(2018年9月)のところCloud Firestore、Realtime Database、Authentication、Cloud Storage、Firebase Messaging、Cloud Functions、Analyticsをサポートしています。公式でも紹介されています。


(2018/1追記)RTDBの記述を現時点で最新のものに差し替えました。
(2018/9追記)angularfireが対応したのでFirestoreの記述に差し替えました。
(2020/6追記)現時点(2020年6月)での最新の内容に書き換えています。


実装内容

angularfireとfirebaseをインストール

まずはプロジェクトにangularfireとfirebaseをインストールします。

cd 自分のプロジェクト
ng add @angular/fire@next
Please select a project:
> NgChat (ngchat-xxx)

(2020/06追記)このコマンドはfirabaseの公式とangularfireの公式で異なっていました。テストする際は実行時のangularfire公式を確認してください。

インストールが完了したら、環境設定を行います。
Firebaseのコンソールを開き、設定>「全般」タブのなかにあるFirebase SDK snippetから「構成」を選択します。
そこに記載されている構成をコピーし、/src/environments/environment.tsを開いて入力します。(<>になっている部分は、自分のapiKeyを入力)

screenshot-console.firebase.google.com-2020.06.18-17_35_31.png

/src/environments/environment.ts
// <>となっている部分は、自分のapiKeyを入力
export const environment = {
  production: false,
  firebase: {
    apiKey: '<your-key>',
    authDomain: '<your-project-authdomain>',
    databaseURL: '<your-database-URL>',
    projectId: '<your-project-id>',
    storageBucket: '<your-storage-bucket>',
    messagingSenderId: '<your-messaging-sender-id>',
    appId: '<your-app-id>',
    measurementId: '<your-measurement-id>',
  }
};

/src/app/app.module.tsを開いて、AngularFireModuleとenvironmentをインポートするよう記述します。

/src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { environment } from '../environments/environment'; // 追加
import { AngularFireModule } from '@angular/fire'; // 追加

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { ChatDatePipe } from './pipe/chat-date.pipe';

@NgModule({
  declarations: [
    AppComponent,
    ChatDatePipe
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    NgbModule,
    FormsModule,
    AngularFireModule.initializeApp(environment.firebase) // 追加,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Angularのモジュール

Angularでは外部ライブラリやコンポーネントなどのクラスを、モジュールで管理しています。
機能単位でモジュールファイルを作成し、@NgModuleデコレータを使ってその機能モジュールに必要なライブラリモジュールやコンポーネント、サービスなどのクラスを管理しています。

@NgModuleデコレータには幾つかのプロパティがあり、それぞれの役割がここでわかるようになっています。主なプロパティは次の通りです。

@NgModule({
  // そのモジュールの中で宣言されているディレクティブ(コンポーネント)とパイプを登録する
  declarations: [], 
  // 自分のモジュールに別のモジュールを取り込む
  imports: [],
  // 他のモジュールでimportsに登録されるものを指定
  exports: [],
  // そのモジュールの中で宣言されているサービスを登録する
  providers: [],
  // アプリケーションのエントリポイントになるコンポーネントを指定
  bootstrap: []
})

次に本プロジェクトで使用するangularfireの機能モジュールをインポートします。
今回作成するアプリでは認証とデータベースを使用するので、AngularFireAuthModuleとAngularFirestoreModuleをインポートします。

/src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { environment } from '../environments/environment'; // 追加
import { AngularFireModule } from '@angular/fire'; // 追加
import { AngularFirestoreModule } from '@angular/fire/firestore'; // 追加
import { AngularFireAuthModule } from '@angular/fire/auth'; // 追加

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { ChatDatePipe } from './pipe/chat-date.pipe';

@NgModule({
  declarations: [
    AppComponent,
    ChatDatePipe
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    NgbModule,
    FormsModule,
    AngularFireModule.initializeApp(environment.firebase), // 追加,
    AngularFirestoreModule,  // 追加
    AngularFireAuthModule,  // 追加
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

これでライブラリの導入は完了です。

Cloud Firestoreを導入する

ライブラリの導入がうまくいっているか、Cloud Firestoreで試してみます。
まずは/src/app/app.component.tsを修正して、AngularFireDatabaseをDI (Dependency Injection)し、このコンポーネントでCloud Firestoreが使えるようにします。

/src/app/app.component.ts
import { Component } from '@angular/core';
import { Comment, User } from './class/chat';
import { AngularFirestore } from '@angular/fire/firestore'; // 追加
import { Observable } from 'rxjs'; // 追加

export class AppComponent {

  item: Observable<Comment>; // 追加
  public content = '';
  public comments = COMMENTS;
  public current_user = CURRENT_USER;

  // DI(依存性注入する機能を指定)
  constructor(db: AngularFirestore) {
    this.item = db
      .collection('comments')
      .doc<Comment>('item')
      .valueChanges();
  }

  // 新しいコメントを追加
  addComment(comment: string) {
     if (comment) {
       this.comments.push(new Comment(this.current_user, comment));
     }
  }

}

次に/src/app/app.component.htmlを修正します。

/src/app/app.component.html
<div class="page">
  <section class="card">
    <div class="card-header">
      NgChat
    </div>
    <div class="card-body">
      <ng-container *ngFor="let comment of comments">
      <div class="media">
        <div class="media-left" *ngIf="comment.user.uid !== currentUser.uid">
          <a href="#" class="icon-rounded">{{comment.initial}}</a>
        </div>
        <div class="media-body">
          <h4 class="media-heading">{{comment.user.name}} Date: {{comment.date | chatDate}}</h4>
          <div>{{comment.content}}</div>
        </div>
        <div class="media-right" *ngIf="comment.user.uid === currentUser.uid">
          <a href="#" class="icon-rounded">{{comment.initial}}</a>
        </div>
      </div>
      <hr>
      </ng-container>
      <!-- Firestoreの反映箇所 -->
      <div class="media">
        <div class="media-left">
          <a href="#" class="icon-rounded">{{(item | async)?.initial}}</a>
        </div>
        <div class="media-body">
          <h4 class="media-heading">{{(item | async)?.user.name}}</h4>
          <div>{{(item | async)?.content}}</div>
        </div>
      </div>
    </div>
  </section>

  <section>
    <form class="chart-form" (submit)="addComment(content)">
      <div class="input-group">
        <input type="text" class="form-control"
               [(ngModel)]="content"
               name="comment"
               placeholder="Comment" />
        <div class="input-group-append">
          <button class="btn btn-info" type="submit">SEND</button>
        </div>
      </div>
    </form>
  </section>
</div>

itemのデータ読み込みの際に、asyncというPipeが使われています。
これはビューへ非同期で読み込む際に使用するPipeです。ここではAngularに採用されているRxjsというライブラリのObservableが利用されていますが、その詳細については別の記事で解説します。

これでクライアント側の準備が整いました。
ng serveを使ってプロジェクトを実行すると、エラーログがコンソールに出力されます。

ERROR in The target entry-point "@angular/fire" has missing dependencies:
 - firebase/app

2020年6月時点で、ng add @angular/fire@nextだけでは十分ではなく、これとは別にfirebaseのライブラリをインストールしておく必要があります。

 npm install firebase --save

後はCloud Firestoreにデータを登録するだけです。
まずはデータの親となるcollection「comments」を登録します。

screenshot-console.firebase.google.com-2020.06.23-00_16_07.png

次に子となる「item」を登録します。

screenshot-console.firebase.google.com-2020.06.23-00_19_43.png

実行結果を確認できるようにするため、すべての書き込み、読み込みを許可できるようにルールを変更します。

screenshot-console.firebase.google.com-2020.06.23-00_27_00.png

実行結果

Jun-23-2020 00-46-43.gif

データベースの更新がリアルタイムでチャットに反映されるのが確認できました。
次はCloud FirestoreのCRUD(Create、Read、Update、Delete)の実装をしていきます。

ソースコード

この時点でのソースコード
※apiKeyは削除しているので、試すときは自身で作成したapiKeyを入れてください。

80
46
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
80
46