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

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

Angular5+Firebaseでチャットアプリを作る② Firebase連携編

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

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

前回は、Angular5とFirebaseを連携して、データベースのデータを反映するところまで完成しました。

今回は、チャットの編集や削除といった機能を実装していきます。

チャットの編集

入力されたチャットはキーで管理されています。

キーは青線の部分です。

このキーを取得し、配列内を編集できるようにしていきます。

配列キーを取得する

配列キーを取得するために、コンポーネントを書き換えていきます。

次のコードを

this.comments = this.commentsRef.valueChanges();

次のように書き換えます。

snapshotChanges:snapshotsの変化を監視します。これはObservableな値を返します。

subscribe:Observableを受け取ります。成功した場合、snapshotsを処理します。

snapshots:配列キーを含んだその配列を取得するためのAngularFireメソッド。また配列キーを含んだ配列のことをスナップショットと言います。

this.comments = snapshots.map:コメント配列にマップ処理したsnapshotsを返します。

map:受け取った値を関数処理する役割を持ちます。今回はsnapshotsとして受け取った複数配列の1つずつのsnapshotを処理します。

snapshot:snapshotsの単数形のAngularFireメソッドです。

const values = snapshot.payload.val():コメントデータをvaluesに代入

snapshot.payload:snapshotのコメントデータが格納されている場所

return new Comment({ key: snapshot.payload.key, …values }):キー値とコメントデータを分けてコメント配列を返します。…は不特定多数の引数を配列として受け取る意味があります。値を定義する場合は中括弧が必要になります。

…の参考元:Rest parameters – JavaScript | MDN

payload.key:配列キーの値

つまり、snapshotChangesによってデータを取得し、subscribeで受取ります。その時の処理として、コメント配列にsnapshots.mapを格納します。とその前に、snapshots.mapの処理をします。map処理はsnapshotsを一つずつにわけたsnapshotからキーとユーザーやイニシャルやメッセージなどのコメントデータをvaluesとして別々にコメント配列に返します。それらの返った配列をコメント配列に格納します。という処理内容になります。

snapshotChangesに合わせる

さらに、commentsはキーと対応したコメント配列をsnapshotChangesで取得することになるので、次のよう書き換えます。

comments: Comment[];

また、commentsがObservableでなくなるのでhtmlの| asyncを外します。

さらに、コメントクラスの型をスナップショットで取得した型に合わせます。

次のように書き換えます。

comment.ts

まず、コメントクラスにキーを含むようにし、isEditは編集中のフラグとして使います。

key?: string;
isEdit : boolean;

さらに、コンストラクターは引数を配列を受け取れるように次のようにします。

values: any

そして、コンストラクター内はコメントデータをvaluesとして受け取るので、各定義にvaluesを加えます。

||:又はという意味で、valuesで受け取れないことも想定しています。

キーだけIf文で定義しているのは受け取れないこともあるからです。

isEditは編集中のフラグなので初期値は編集中ではないfalseとしておきます。

さて、コメントクラスの定義を変更したので、addComment内のPush処理内も変更します。

new Comment({ user: this.currentUser, message: comment })

コメント配列の引数の指定が、ユーザーとメッセージではなくなったので各要素の定義が必要になります。

これでキーを取得する機能が実装できました。

編集と削除アイコンを表示させる

では、キーが取得できるようになったので、編集と削除を実装していきましょう。

まずは、ブラウザにキーバインドとなるアイコンを表示させます。

font-awesomeを使っていきます。

font-awesomeはアイコンをフォントとして埋め込めるサービスを提供している中の一つです。

次のコマンドをターミナルで実行します。

そのまえにサーバーを一旦、落としておきましょう。うまくインストールされないことがあります。
コマンド npm install font-awesome

Bootstrapのように.angular-cli.jsonのスタイル内に次のコードを加えます。

“../node_modules/font-awesome/css/font-awesome.css”,

では、読み込めているかの確認も含めてhtmlを編集していきます。

<pre>{{ comment.message }}</pre>

この部分を次のように書き換えます。

編集中フラグのisEditによって生成するhtmlは変わるようにしました。

編集中でない場合はコメントをそのまま表示して、編集中であれば、編集用のテキストエリアを表示し、入力値をcomment.messageとしてngModelでコンポーネントに受け渡します。

そして保存ボタンとキャンセルボタンを用意しています。このボタンのクリックイベントについては後ほど実装します。

さらに、class=”media-heading”タグ内に次のコードを加えます。

これは投稿したチャットが自分の投稿なら編集や削除のアイコンを表示するコードになります。

まだ、クリックイベントを定義していませんがこれで、アイコンは表示されるようになりました。

確認してみましょう。次のようになるはずです。

無事アイコンが表示されました。

アイコンの種類はfa fa-editがエディットアイコンでfa fa-trashが削除アイコンです。

edit | edit | Font Awesome  trash-alt | trash-alt | Font Awesome

これらはiタグのクラスで指定しています。

さらに見栄えを良くするためスタイルシートに次のコードを加えます。

styles.css

cursor: pointer:アイコンにマウスを合わせるとリンクカーソルに変わります。

さらにエディットボタンのサイズと位置を調整しました。

では、クリックイベントを実装して編集や削除ができるようにしていきます。

編集・削除イベントを実装する

まず、*ngFor内に; let i = indexを追加します。

一般的なfor文のようにi値を基に処理を行うために加えます。

次に編集エリアの表示切り替えができるようにコンポーネントにメソッドを追加していきます。

toggleEditComment(index: number): void {
this.comments[index].isEdit = !this.comments[index].isEdit;
}

○番目にindexされたコメントの編集中フラグをがあるのでfalseからtrueに変えるえることになります。

そのため、*ngIf=”comment.isEdit”タグ内の編集中のhtmlが生成されることになりました。

編集エリアが開くようになりました。

また、もう一度編集アイコンをクリックしたり、キャンセルをクリックするとtoggleEditCommentが実行されるのでtrueからfalseに変わり編集終了になります。

次に編集の保存用のメソッドを作っていきます。

commentsRef.update(key,・・・):keyに対応したサーバーのデータを・・・に更新します。第二引数には変更後のコメントとその時の日付を指定します。

さらに、この処理をする時には、編集中フラグをtrueからfalseして、編集終了にします。

では、最後に削除イベントです。

deleteComment(key: string): void {
this.commentsRef.remove(key);
}

これだけiを使っていないのはデータベース側でデータを削除すれば済むからです。

保存の処理はコンポーネントで一旦、変更値を格納する必要があったので格納先を指定するiが必要でした。

さて、これで自分だけが使う分には問題なく動くようになりました。

あとはユーザー認識という大事な機能があるのですがその前にコンポーネントの整理をしていきます。

次回はアプリ構成の見直しとユーザー新規登録

さて、今回は編集と削除の機能を実装しました。

ついでに、Observableのときのsubscribeの書き方だったり、mapの使い方だったり、*ngForのiの使い方だったり、これまでで一番文字数が少ない割に厄介なコードが多くありました。

特に、subscribeのところが全然わかりませんでした。

なんで「=>があるの?」という状態だったので当たり前ですが・・・。

教材の中の「RxJSを理解しよう」を見てみたり、実際にコードをいじってみてVSCがどこをいじるとエラーになるか試したりしてようやくわかりました。

では、一旦リフレッシュして、またアプリ開発始めてみたいと思います。

次回は、アプリ構成の見直しとユーザー新規登録です。

今はコンポーネントに全て書いていますが機能を分散させていきます!

そして、Firebaseを設定してメールアドレスでユーザー登録できるようにしていきます。