僕は技術ができない

技術のできないスーツ園児ニアが考えていること

Angular で Firebase の Database, Storage データを読み取るまでの流れ

前回は Angular プロジェクトを Firebase にデプロイし、アクセスするまでをやりました。

www.contemporarycuz.com

今回は、Firestore や Storage につないでデータを表示するところまでをやります。

ケースとしては、とりあえずアプリをデプロイして繋ぐことができればOKというガバガバ仕様を想定してますので予めご了承ください。

Firebase 側での作業

Config の取得

Firebaseコンソールの「Project Overview」から、</> (Webアプリ)を選択し、アプリを登録します。

f:id:contemporarycuz:20190917170145p:plain

f:id:contemporarycuz:20190917170452p:plain

SDK Snippet からアプリのConfig類をコピーしておきます。

f:id:contemporarycuz:20190917171050p:plain

Firestore へのデータ登録

コレクションを作成します。

f:id:contemporarycuz:20190917175143p:plain

今回は以下の設定で作成しました。

  • コレクション ID:hoge-collection
  • ドキュメント ID:hoge-doc

こんな感じです。

f:id:contemporarycuz:20190917175356p:plain

Firestorage へのデータ登録

適当にファイルをアップロードします。

f:id:contemporarycuz:20190917181642p:plain

アクセス権をガバガバにします。以下のように読み取りアクセスをパブリックに向けます。

f:id:contemporarycuz:20190917191852p:plain

とりあえず、Firebase側での作業はこれで終わりです。

ローカル側での作業

アプリをFBのリソースを利用するように書き換えます。

Firebase モジュールのインポート

@angular/fire パッケージをインストール(npm リファレンス

$ npm install --save firebase @angular/fire

src/app/app.module.ts を書き換えます。

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { AngularFireModule } from '@angular/fire';  // 追記
import { AngularFireAuthModule } from '@angular/fire/auth';  // 追記
import { AngularFirestoreModule } from '@angular/fire/firestore';  // 追記
import { AngularFireStorageModule } from '@angular/fire/storage';  // 追記

var firebaseConfig = {
  apiKey: "(略)",
  authDomain: "(略)",
  databaseURL: "(略)",
  projectId: "(略)",
  storageBucket: "(略)",
  messagingSenderId: "(略)",
  appId: "(略)"
};

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    AngularFireModule.initializeApp(firebaseConfig),  // 追記
    AngularFireAuthModule,  // 追記
    AngularFirestoreModule,  // 追記
    AngularFireStorageModule  // 追記
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

テスト用にコンポーネントを用意

コンポーネントを生成します。

$ ng generate component firestore
$ ng generate component firestorage

ルーティング設定をします。

src/app/app-routing.module.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { FirestoreComponent } from './firestore/firestore.component'; // FirestoreComponentをimport
import { FirestorageComponent } from './firestorage/firestorage.component'; // FirestorageComponentをimport


const routes: Routes = [
  {path: 'firestore', component: FirestoreComponent}, // FirestorageComponentを追加
  {path: 'firestorage', component: FirestorageComponent} // FirestoreComponentを追加
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

デフォルトのトップページが邪魔なので消します。

src/app/app.component.html

<router-outlet></router-outlet>

疎通確認します。

$ ng serve --open

f:id:contemporarycuz:20190917173536p:plain

Firestore コンポーネントの書き換え

適当に書き換えます。このdataにFirestoreに登録したデータを表示させます。 src/app/firestore/firestore.component.html

<div>
    <p>firestore works!</p>
</div>
<div>
    <p>{{data}}</p>
</div>

src/app/firestore/firestore.component.ts

import { Component, OnInit } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore'; // @angular/fire/firestore のインポート

@Component({
  selector: 'app-firestore',
  templateUrl: './firestore.component.html',
  styleUrls: ['./firestore.component.css']
})
export class FirestoreComponent implements OnInit {
  data: string = 'this variable is from firestore'; // 変数の初期化

  constructor(private firestore:AngularFirestore) { }

  // データベースの読み取り(hoge-collection -> hoge-doc -> hoge-field)
  ngOnInit() {
    this.firestore.collection('hoge-collection').doc('hoge-doc').valueChanges().subscribe((value)=>{
      this.data = value['hoge-field'];
    });
  }

}

疎通確認します。

f:id:contemporarycuz:20190917175956p:plain

Firestoreの値を書き換え、リアルタイムに画面も更新されるか見てみましょう。

f:id:contemporarycuz:20190917180202p:plain

Firestorage コンポーネントの書き換え

src/app/firestorage/firestorage.component.html

<div>
    <p>firestorage works!</p>
</div>
<div>
    <img id="image" src="" />
</div>

src/app/firestorage/firestorage.component.ts

import { Component, OnInit } from '@angular/core';
import { AngularFireStorage } from '@angular/fire/storage';

@Component({
  selector: 'app-firestorage',
  templateUrl: './firestorage.component.html',
  styleUrls: ['./firestorage.component.css']
})
export class FirestorageComponent implements OnInit {

  constructor(private storage:AngularFireStorage) {  }

  ngOnInit() {
    this.storage.storage.ref('angular.png').getDownloadURL().then((url) => {
      var img = (<HTMLInputElement>document.getElementById('image'));
      img.setAttribute('src', url);
    });
  }
}

(参考)TypescriptでHTMLElementを使う方法

stackoverflow.com

TypescriptもAngularもわからないマンなので document.getElementById を使わずに Angular で正しく実装する方法がよくわからず、、、 だれか教えてください。

疎通確認します。

$ ng serve --open

f:id:contemporarycuz:20190917212939p:plain

Firebase にデプロイ

ビルド&デプロイ

$ ng build --prod
$ firebase deploy

デプロイ先で疎通確認

f:id:contemporarycuz:20190917214418p:plain