Angular + FirebaseでCRUD機能を実現

###### 前々回：[Angularの新規プロジェクト作成手順 - material2とService Workerは使いたい](https://qiita.com/atomyah/items/3e125b072dd74181e582)

###### 前回：[AngularプロジェクトにFirebaseを導入設定](https://qiita.com/atomyah/items/750d076e3dd5449423fd)

<br />

今回はFirebaseと連携してCRUDシステムを構築してみる備忘録。備忘録のみならず、人に教えるときの参考資料にもなりそうかもしれない。とにかくAngular＋Firebaseでやるとなるとホントに正しいやり方ってのがよくわからない。ま、いいか。

<br />

CRUDとは、データベースを利用する基本的な４つの機能。Create（生成）、Read（読み取り）、Update（更新）、Delete（削除）の頭文字をとった言葉。

<br />

FirebaseではFirestoreというnosqlデータベースが用意されている。それぞれの名称は以下のように理解すればいい。

**コレクション**：RDBにおけるテーブル
**ドキュメント**：RDBにおける行（レコード）
**フィールド**：RDBにおける列（カラム）

<br />

### まずFirestoreを準備

データベースの作成ボタンをクリック。
![1554182251715.png](https://qiita-image-store.s3.amazonaws.com/0/307441/dfa8d2f8-7072-8131-be99-cbb0ad4c807c.png)

<br />
テストモードで有効にする。
![1554182316601.png](https://qiita-image-store.s3.amazonaws.com/0/307441/3fcd9741-d39c-a098-c9e5-baac22b6799f.png)
<br />

コレクションを追加ボタンをクリック、コレクションIDにcommentsと入力して次へ
![1554182439851.png](https://qiita-image-store.s3.amazonaws.com/0/307441/aea9af5d-9110-fbb9-0635-106e065bb710.png)

<br />

こんな風に入力して保存。ドキュメントIDはユニークIDみたいなもの。

userフィールドが入れ子になってる以外はcommentsテーブルを作りましたーてのと同じやね。
![1554182602796.png](https://qiita-image-store.s3.amazonaws.com/0/307441/8d0782fe-c7c3-f694-c115-86f7cb859f57.png)

<br />

ではAngularに戻って・・・

どこでもいいのだけど、appの下にでもclassフォルダを作成する。

<br />

したら、インターフェースを作成する。次のコマンド。


```cmd
C:\project\projectA>ng g interface class/comments
```



comments.tsができましたよ、と。

![1554184131544.png](https://qiita-image-store.s3.amazonaws.com/0/307441/f9525c26-7542-b24c-47b0-98ae0abe2294.png)

<br />

comments.tsには次のように記述
RDBにおけるテーブルのスキーマを作成したみたいな感じ。

```cmd
export interface Comments {
    content:string;
    initial:string;
    user: {
        name: string;
    },
}
```

<br />




### ようし、ではデータを閲覧してみよう



コレクションへの接続は、なんかいろいろやり方があるようだが**AngularFirestoreCollection**を使うのが分かりやすいとおもった。つまり…

`this.commentsRef = this.db.collection<Comments>('comments');`

この1行でコレクションへの接続もできれば、まだそれが存在しない場合、自動的に作成してくれるよう。そしてドキュメントがないコレクションは自動的に削除されるとな。

そして*valueChanges()*をコールすれば、該当コレクションの変化を常に監視状態になる。

`this.comment$ = this.commentsRef.valueChanges();`



※ `import { Observable } from 'rxjs';`は今時点では知る必要ない。でも書いておく必要がある。


<br />

で、コードとしてはこうなる。

###### app.component.ts

```typescript
import { Component, OnInit } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore';
import { Comments } from '../../class/comments';  // commentsデータタイプインターフェース。
import { Observable } from 'rxjs'; // 正式名称「Reactive Extensions for JavaScript」

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

  commentsRef: AngularFirestoreCollection<Comments>; //Commentsはcomments.tsからエキスポートされているよ！
  comments: Observable<Comments[]>; // これも意味わからんが呪文と思っとけ！

  constructor(private db: AngularFirestore) {
    this.commentsRef = this.db.collection<Comments>('comments');
    this.comments = this.commentsRef.valueChanges();
   }

   ngOnInit() {
  }

}
```



######app.component.html

```html
  <table border="1" width="80%">
      <thead>
        <tr><th>content</th><th>initial</th><th>name</th></tr>
      </thead>
      <tbody>
      <tr *ngFor="let item of comments | async">
        <td>{{ item.content }}</td>
        <td>{{ item.initial }}</td>
        <td>{{ item.user.name }}</td>
      </tr>
      </tbody>
  </table>
```

<br/>

こんな感じ。オケオケ


![1554214329725.png](https://qiita-image-store.s3.amazonaws.com/0/307441/7a9bf726-685a-1e63-fea5-3d35ef4b8b0f.png)


<br/>

### ようし、ではデータを追加してみよう

ただコレクションリファレンスからaddを呼び出せばよい。`commentsRef.add`

```typescript
addCommentData(content:string, initial:string, username:string) {
  this.commentsRef.add(
    { content: this.content.value, 
      initial: this.initial.value,
      user: {
        name: this.username.value
      }
    });
}
```


<br/>


のだが・・・

フォームを作成・操作するのに**FormControl**をインポートする必要がある。

`import { FormControl } from '@angular/forms';`

<br/>

そうしたら、フォームコントロールを作成して、その値をAddすればよい。

```typescript
  /** フォームコントロール */
  content = new FormControl('');
  initial = new FormControl('');
  username = new FormControl('');

  /** コレクションリファレンスからaddするメソッド*/
addCommentData(content:string, initial:string, username:string) {
  this.commentsRef.add(
    { content: this.content.value, 
      initial: this.initial.value,
      user: {
        name: this.username.value
      }
    });
}
```



html

```html
    <div class="example-container">
        <mat-form-field>
           <mat-label>content</mat-label>
             <input matInput placeholder="Textarea" [formControl]="content" required>
       </mat-form-field>
       <mat-form-field>
           <mat-label>initial</mat-label>
             <input matInput placeholder="Input" [formControl]="initial" required>
       </mat-form-field>
       <mat-form-field>
           <mat-label>name</mat-label>
             <input matInput placeholder="Input" [formControl]="username" required>
       </mat-form-field>
             <br />
       <button type="submit" mat-flat-button color="accent">add comment</button>
   </div>
```



 [formControl]しか必要ない（`<form>` タグがない）。

一番簡単な方法。FormControlを使うだけ。

<br />

しかしこれだとどんなデータでもカラデータでも追加できてしまう。**Validatorの仕組みは絶対必要だろう**。

![1554214864781.png](https://qiita-image-store.s3.amazonaws.com/0/307441/b524c776-3290-4647-a7df-8ae32dcff732.png)

<br />

Vlidatorを使うには**FormGroup**を作成する必要がある（たぶん。[[水無瀬のプログラミング日記](https://minase-program.hatenablog.com/)]<https://minase-program.hatenablog.com/entry/2018/10/30/011324>を見るとそうでもなさそうだが調べるのが面倒）。

で、以下をインポート。

`import { FormBuilder,FormControl,FormGroup,Validators } from '@angular/forms';`

コンストラクタには`private fb: FormBuilder`を追記。

<br />

コードとしてはこうなる。

###### app.component.ts

```typescript
import { Component, OnInit } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore';
import { Comments } from '../../class/comments';  // commentsデータタイプインターフェース
import { Observable } from 'rxjs'; // 正式名称「Reactive Extensions for JavaScript」
import { FormBuilder,FormControl,FormGroup,Validators } from '@angular/forms'; // 追記

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

  commentsRef: AngularFirestoreCollection<Comments>;
  comments: Observable<Comments[]>;

  constructor(private db: AngularFirestore, private fb: FormBuilder) {// FormBuilderを追加
    this.commentsRef = this.db.collection<Comments>('comments');
    this.comments = this.commentsRef.valueChanges();
   }


  //フォームグループ
  commentForm: FormGroup;
  
  //Validatorを作成
  ngOnInit() {
    this.commentForm = this.fb.group({
      content:  ['', [
        Validators.required
      ]],
      initial:  ['', [
        Validators.required,
        Validators.maxLength(1)
      ]],
      username:  ['', 
        Validators.required
      ]
    });
  }

  // ゲッターを作成
  get content() {
    return this.commentForm.get('content')
  }
  get initial() {
    return this.commentForm.get('initial')
  }
  get username() {
    return this.commentForm.get('username')
  }

  // データ追加メソッド
  addCommentData(content:string, initial:string, username:string) {
    this.commentsRef.add({ 
      content: this.content.value, 
      initial: this.initial.value,
      user: {
        name: this.username.value
      },
    });
  }
}

```



###### app.component.html

```html
<div class="myContainerMain">

  <table border="1" width="80%">
      <thead>
        <tr><th>content</th><th>initial</th><th>name</th></tr>
      </thead>
      <tbody>
      <tr *ngFor="let item of comments | async">
        <td>{{ item.content }}</td>
        <td>{{ item.initial }}</td>
        <td>{{ item.user.name }}</td>
      </tr>
      </tbody>
    </table>


<form [formGroup]="commentForm" (ngSubmit)="addCommentData()">
    <div class="example-container">
        <mat-form-field>
           <mat-label>content</mat-label>
             <input matInput placeholder="Textarea" formControlName="content" required>
       </mat-form-field>
       <mat-form-field>
           <mat-label>initial</mat-label>
             <input matInput placeholder="Input" formControlName="initial" required>
       </mat-form-field>
       <mat-form-field>
           <mat-label>name</mat-label>
             <input matInput placeholder="Input" formControlName="username" required>
       </mat-form-field>
             <br />
       <button type="submit" mat-flat-button color="accent"  [disabled]="!commentForm.valid">add comment</button>
   </div>
</form>

</div>
```



`<form [formGroup]="commentForm" (ngSubmit)="addCommentData()">`

[formGroup]="フォームグループ名"、そして (ngSubmit)="追加メソッド名"ね。`<form>`タグに。

`<button`タグは type="submit"にしておく。で、Validatorがfalseを返したらDisable状態にする`[disabled]="!commentForm.valid"`のフレーズを。

<br />

意外とこうやってHTML側を示してくれている記事ないんだよなあ。


<br />

Validators.required`が効いてるので、nameを入力しないとadd commentボタンが押せなくなった。
![1554373961781.png](https://qiita-image-store.s3.amazonaws.com/0/307441/c5e3a427-7699-ed61-e6bb-16c16ece7847.png)

<br />




### ようし、ではデータを変更してみよう



コレクションを更新するには、アイテムのIDのようなものを取得しなければならない。

それはFirestoreの場合自動的に付与される20桁の英数字の羅列。
![1554271366346.png](https://qiita-image-store.s3.amazonaws.com/0/307441/271ab1b8-c66e-5acc-fedc-597f5800f2fc.png)


<br />


これらを得るためにはvalueChange()ではダメでsnapshopChange()を使うのだと。

```typescript
import { Component, OnInit } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore';
import { Comments } from '../../class/comments';  // commentsデータタイプインターフェース
import { Observable } from 'rxjs'; // 正式名称「Reactive Extensions for JavaScript」
import { FormBuilder,FormControl,FormGroup,Validators } from '@angular/forms';
import { map } from "rxjs/operators"; // 追加

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

  commentsRef: AngularFirestoreCollection<Comments>;
  comments: Observable<Comments[]>;

  constructor(private db: AngularFirestore, private fb: FormBuilder) {
    this.commentsRef = this.db.collection<Comments>('comments');
    this.comments = this.commentsRef.snapshotChanges().pipe
      (map(actions => {
      return actions.map(action => {
        const data = action.payload.doc.data() as Comments;
        const id = action.payload.doc.id;
        return { id, ...data };
        });
      }));      
  }
  
    …後略…
```

`import { map } from "rxjs/operators"; `を追加。

あとはthis.commentsRef.snapshotChanges()…以降のコードはコピペ。理解せんでも良い。

最後に`return { id, ...data };`とあるのでidも含めたデータも返してくれていることだけ確認。

ためしにHTMLも以下のように編集。

```html
  <table border="1" width="80%">
      <thead>
        <tr><th>id</th><th>content</th><th>initial</th><th>name</th></tr>
      </thead>
      <tbody>
      <tr *ngFor="let item of comments | async">
        <td>{{ item.id }}</td>
        <td>{{ item.content }}</td>
        <td>{{ item.initial }}</td>
        <td>{{ item.user.name }}</td>
      </tr>
      </tbody>
    </table>

    …後略…
```



`<td>{{ item.id }}</td>`を追加しただけ。

<br/>


なっ、idの値が表示されてる。
![1554271809471.png](https://qiita-image-store.s3.amazonaws.com/0/307441/3b29b8d7-a859-454b-4d40-c1aa199ffebd.png)

<br/>

これであとは

更新の場合：

```typescript
updateComment(comments: Comments) {
  this.commentsRef.doc(comments.id).update(……処理……);
}
```



削除の場合

```typescript
deleteComment(comments: Comments) {
  this.commentsRef.doc(comments.id).delete();
}
```



こんな感じになろうや。

<br/>

まずはわかりやすくHTMLにボタンを置く。
![1554279311841.png](https://qiita-image-store.s3.amazonaws.com/0/307441/46b25654-e3b5-c61c-1feb-248ea6bf8951.png)


<br/>


編集ボタンと削除ボタンを置いた。

```html
  <table>
      <thead>
        <tr><th>id</th><th>content</th><th>initial</th><th>name</th><th></th><th></th></tr>
      </thead>
      <tbody>
      <tr *ngFor="let item of comments | async">
        <td>{{ item.id }}</td>
        <td>{{ item.content }}</td>
        <td>{{ item.initial }}</td>
        <td>{{ item.user.name }}</td>
        <td>
            <div class="example-button-row">
                <button mat-button color="accent">編集</button><!-- 追加 -->
            </div>
        </td>
        <td>
            <div class="example-button-row">
                <button mat-button color="warn">削除</button><!-- 追加 -->
            </div>
        </td>
      </tr>
      </tbody>
    </table>

…以下略…
```

<br/>

次に編集ボタンを押すと該当データを編集できるようにする。

ここからがたいへん。

まず、edit_flagという編集モード変数（boolean)を作成する。
<br>
###### comments.ts

```json
export interface Comments {
    id?: string; // 追加
    content:string;
    initial:string;
    user: {
        name: string;
    },
    edit_flag?: boolean; // 追加
}
```

`edit_flag?: boolean;` を追加。はてなマークは、`Comments`クラスになくてもいい一時的に利用するよーという意味。あと、idもさっき書かなかったけど、編集保存するときに利用するのではてなマーク付きで追加しておく。

<br/>

そうしたら、app.component.tsに以下のメソッドを追記。

```typescript
  // 編集フィールドの切り替え
  toggleEditComment(item: Comments) { // 追加
    return item.edit_flag = (!item.edit_flag); //booleanを反転させる
  }
```

<br/>

このメソッドはな、編集ボタンにつけるんだ。

```html
<td>
  <div class="example-button-row">
     <button mat-button color="accent" (click)="toggleEditComment(item)">編集</button><!-- 追加 -->
  </div>
</td>
```

`(click)="toggleEditComment(item)"`を追記した。

<br/>

そうすると、編集ボタンをクリックするたびに、edit_flagという編集モード変数が切り替わる。

初期値はなぜかfalse、というかヌル？

一度押すとtrueになる。

も一度押すとfalseになる。

<br/>

この作用を利用して、edit_flagがtrueのときのみ、データ表示部分がInput textフォームに切り替わるようにする。

それを実現したHTMLが以下のとおり。

<br/>

###### app.component.html

```html
<div class="myContainerMain">
  <table>
      <thead>
        <tr><th>id</th><th>content</th><th>Intl</th><th>name</th><th>edit_flag</th><th>edit button</th><th>delete button</th></tr>
      </thead>
      <tbody>
      <tr *ngFor="let item of comments | async">       
        <td>{{ item.id }}</td>
      <!-- edit_flagによって編集フィールドを切り替える -->
        <td>  
          <ng-container *ngIf="!item.edit_flag">
            {{item.content}}
          </ng-container>
          <ng-container *ngIf="item.edit_flag">
              <input type="text" class="form-control" [(ngModel)]="item.content" name="edit_content"><!-- 追加 -->
          </ng-container>
        </td>
        <td>
          <ng-container *ngIf="!item.edit_flag">          
            {{ item.initial }}
          </ng-container>
          <ng-container *ngIf="item.edit_flag">
              <input type="text" size="1" class="form-control" [(ngModel)]="item.initial" name="edit_initial"><!-- 追加 -->
          </ng-container>            
        </td>
        <td>
          <ng-container *ngIf="!item.edit_flag">  
            {{ item.user.name }}
          </ng-container>
          <ng-container *ngIf="item.edit_flag">
              <input type="text" class="form-control" [(ngModel)]="item.user.name" name="edit_username"><!-- 追加 -->
          </ng-container>                  
        </td>
        <td>{{ item.edit_flag }}</td><!-- 追加 -->
        <td>
            <div class="example-button-row">
              <ng-container *ngIf="!item.edit_flag">  
                <button mat-button color="accent" (click)="toggleEditComment(item)">編集</button>
              </ng-container>
              <ng-container *ngIf="item.edit_flag">
                  <button mat-button color="accent" (click)="toggleEditComment(item)">編集やめる</button><!-- 追加 -->
              </ng-container>  
            </div>
        </td>
        <td>
            <div class="example-button-row">
             <ng-container *ngIf="!item.edit_flag">  
                <button mat-button color="warn">削除</button>
             </ng-container>
             <ng-container *ngIf="item.edit_flag">
                <button mat-button color="primary" (click)="saveEditComment(item)">保存</button><!-- 追加 -->
            </ng-container>  
            </div>
        <!-- edit_flagによる切り替え作業ここまで -->
        </td>
      </tr>
      </tbody>
    </table>

    <br /><br />

    <form [formGroup]="commentForm" (ngSubmit)="addCommentData()">
        <div class="example-container">
            <mat-form-field>
               <mat-label>content</mat-label>
                 <input matInput placeholder="Textarea" formControlName="content">
           </mat-form-field>
           <mat-form-field>
               <mat-label>initial</mat-label>
                 <input matInput placeholder="Input" formControlName="initial">
           </mat-form-field>
           <mat-form-field>
               <mat-label>name</mat-label>
                 <input matInput placeholder="Input" formControlName="username">
           </mat-form-field>
                 <br />
           <button type="submit" mat-flat-button color="accent"  [disabled]="!commentForm.valid">add comment</button>
       </div>
    </form>



</div>
```



`<ng-container></ng-container>` でくくった中。（`*ngIf`を使う時は`<ng-container>`を使うもんだと思っておけばよい。`<div>` `<td>`にも付けられるが…）

`<ng-container *ngIf="!item.edit_flag">`　： edit_flagがFalseの場合は普通に表示。

`<ng-container *ngIf="item.edit_flag">`　： edit_flagがTrueの場合は編集モードで表示。



<br>

結果がこれ。
![1554372676780.png](https://qiita-image-store.s3.amazonaws.com/0/307441/ef60cfb1-c178-ebec-c518-c87f1ffbba99.png)

<br>
編集ボタンを押すと、
![1554372732461.png](https://qiita-image-store.s3.amazonaws.com/0/307441/4a67d750-2990-3f1b-71da-bd866878134c.png)

<br>


編集をやめるボタンを押すと、
![1554372792106.png](https://qiita-image-store.s3.amazonaws.com/0/307441/1f276f00-0956-1df7-5513-36e1d2167b7a.png)


<br>

それぞれの場合で表示されるボタンも変えている。

オケオケ



あとは「保存」ボタンに加えた` (click)="saveEditComment(item)"`のコードをapp.component.tsに書き足すだけ。

```typescript
  // 編集内容を保存
  saveEditComment(item: Comments) { // 追加
    this.db
      .collection('comments')
      .doc(item.id)
      .update({
        content: item.content,
        initial: item.initial,
        user: {
          name: item.user.name
        },
      })
      .then(() => {
        alert('コメントを更新しました');
        item.edit_flag = false;
      });
  }
```

<br>


では編集してみよう。

<br>

テストで最初にFirestoreに作成したAtom Yahを編集する。

編集ボタンをクリック。
![1554373225708.png](https://qiita-image-store.s3.amazonaws.com/0/307441/fba610c5-7569-51b7-312f-f53cc5e681b3.png)

<br>

編集する
![1554373291584.png](https://qiita-image-store.s3.amazonaws.com/0/307441/680a4a1c-be93-f2f4-dbfc-db0f2c183c23.png)

<br>

保存ボタンをクリック
![1554373335433.png](https://qiita-image-store.s3.amazonaws.com/0/307441/a0672d74-2bac-1139-fa15-346f4eb19afe.png)

<br>

Firestoreのコレクションも変更されている
![1554373422602.png](https://qiita-image-store.s3.amazonaws.com/0/307441/52e18c0b-8a6a-fcd8-37da-0bfbe6d1af73.png)


<br>

念のため、ここまでのapp.component.ts全文

###### app.component.ts

```typescript
import { Component, OnInit } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore';
import { Comments } from '../../class/comments';  // commentsデータタイプインターフェース
import { Observable } from 'rxjs'; // 正式名称「Reactive Extensions for JavaScript」
import { FormBuilder,FormControl,FormGroup,Validators } from '@angular/forms';
import { map } from "rxjs/operators"; // 追加

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

  commentsRef: AngularFirestoreCollection<Comments>;
  comments: Observable<Comments[]>;

  constructor(private db: AngularFirestore, private fb: FormBuilder) { // FormBuilderを追加
    this.commentsRef = this.db.collection<Comments>('comments');
    this.comments = this.commentsRef.snapshotChanges().pipe
      (map(actions => {
      return actions.map(action => {
        const data = action.payload.doc.data() as Comments;
        const id = action.payload.doc.id;
        return { id, ...data };
        });
      }));      
  }
  

/* ここからは追加用コード */

  //フォームグループ
  commentForm: FormGroup;

  //Validatorを作成
  ngOnInit() {
    this.commentForm = this.fb.group({
      content:  ['', [
        Validators.required
      ]],
      initial:  ['', [
        Validators.required,
        Validators.maxLength(1)
      ]],
      username:  ['', 
        Validators.required
      ]
    });  
  }
  // ゲッターを作成
  get content() {
    return this.commentForm.get('content')
  }
  get initial() {
    return this.commentForm.get('initial')
  }
  get username() {
    return this.commentForm.get('username')
  }

  // データ追加メソッド
  addCommentData(content:string, initial:string, username:string) {
    this.commentsRef.add({ 
      content: this.content.value, 
      initial: this.initial.value,
      user: {
        name: this.username.value
      },
    });
  }


  

/* ここからは編集用コード */

  // 編集フィールドの切り替え
  toggleEditComment(item: Comments) { // 追加
    return item.edit_flag = (!item.edit_flag); //booleanを反転させる
  }
  
  
  // 編集内容を保存
  saveEditComment(item: Comments) { // 追加
    this.db
      .collection('comments')
      .doc(item.id)
      .update({
        content: item.content,
        initial: item.initial,
        user: {
          name: item.user.name
        },
      })
      .then(() => {
        alert('コメントを更新しました');
        item.edit_flag = false;
      });
  }
}

```


<br>


### さいご。削除は簡単だ

<br>
削除メソッドを追加するだけ

###### app.component.ts

```typescript
  // コメントを削除する
  deleteComment(item: Comments) { // 追加
    this.db
      .collection('comments')
      .doc(item.id)
      .delete()
      .then(() => {
        alert('コメントを削除しました');
      });
  }
```



###### app.components.html

```html
<div class="example-button-row">
  <ng-container *ngIf="!item.edit_flag">  
   <button mat-button color="warn" (click)="deleteComment(item)">削除</button><!-- 追加 -->
  </ng-container>
  <ng-container *ngIf="item.edit_flag">
```

<br>

一番最初につくったダミーデータを削除ボタンをクリックして削除
![1554443024656.png](https://qiita-image-store.s3.amazonaws.com/0/307441/49424ef4-c585-a376-6670-7a6eb22eae2d.png)

<br>
削除された
![1554443049866.png](https://qiita-image-store.s3.amazonaws.com/0/307441/e04e0f0b-c012-3955-57c5-c1a11e4255f5.png)

<br>

Firestoreでもitem ドキュメントは消えた。
![1554443144401.png](https://qiita-image-store.s3.amazonaws.com/0/307441/60c26f2a-12f4-54ce-0fa9-1e14033163d0.png)


<br>



おわり。
よかよか。

<br />

githubはこちらに。
[Angular + FirebaseでCRUD機能を実現](https://github.com/atomyah/ProjectA)


<br>

### 参考：

###### [Using Cloud Firestore in Angular With AngularFire]<https://alligator.io/angular/cloud-firestore-angularfire/>

###### [Angular 7 Firebase 5 CRUD Operations with Reactive Forms]<https://www.positronx.io/angular-7-firebase-5-crud-operations-with-reactive-forms/>

###### [Angular+Cloud FirestoreでCRUD(CREATE, READ, UPDATE, DELETE)を実装する]<https://qiita.com/Yamamoto0525/items/c1ec1b7ce2350b294aeb>