18
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

AngularのngIfとsubmitイベントでチャットコメントを実装する

Last updated at Posted at 2016-09-26

この記事はAngular+Firebaseでチャットアプリを作るのエントリーです。
前記事:AngularのngForでチャットコメントを実装する
次記事:AngularのPipeを使って、日付を変換する

この記事で行うこと

本稿では、AngularのビルトインディレクティブであるngIfとsubmitイベントを使って、前回に引き続きDOMを操作していきます。


(追記:2020/6)現時点(2020年6月)での最新の内容に書き換えています。


実装内容

ngIfで自分のコメントを表示させる

自分と自分以外を判別するフラグをつける

前回、定数として作成したCOMMENTSに、userとinitialというプロパティを追加し、自分のユーザー情報を作成します。
それに合わせて、定義ファイルchat.tsも更新します。

src/app/class/chat.ts
export class User { // Userの定義を追加
  uid: number;
  name: string;

  constructor(uid: number, name: string) {
    this.uid = uid;
    this.name = name;
  }
}

export class Comment { // Commentの定義を変更
  user: User;
  initial: string;
  content: string;

  constructor(user: User, content: string) {
    this.user = user;
    this.initial = user.name.slice(0, 1);
    this.content = content;
  }
}
src/app/app.component.ts
import { Component } from '@angular/core';
import { Comment, User } from './class/chat'; // Userを追加


const CURRENT_USER: User = new User(1, 'Tanaka Jiro'); // 自分のUser情報を追加
const ANOTHER_USER: User = new User(2, 'Suzuki Taro'); // 相手のUser情報を追加
const COMMENTS: Comment[] = [ // クラスを元にコメントを作成
  new Comment(ANOTHER_USER, 'Suzukiの1つ目のコメントです。'),
  new Comment(ANOTHER_USER, 'Suzukiの2つ目のコメントです。'),
  new Comment(CURRENT_USER, 'Tanakaの1つ目のコメントです。'),
  new Comment(ANOTHER_USER, 'Suzukiの3つ目のコメントです。'),
  new Comment(CURRENT_USER, 'Tanakaの2つ目のコメントです。')
];

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  public content = '';
  public comments = COMMENTS;
  public currentUser = CURRENT_USER; // 追加
}

ngIfで自分のuidを判別し、自分のコメントとして表示させる

ngIfは、条件式の値がtureの時にDOMを表示させるビルトインディレクティブです。
commentのuidとCURRENT_USERのuidを比較して、値が等しい時は右側に自分のアイコンが出るよう設定します。

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">
        <!--current_user.uidとcomment.user.uidが等しくない場合に表示-->
        <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:2016/09/01</h4>
          <div>{{comment.content}}</div>
        </div>
        <!--current_user.uidとcomment.user.uidが等しい場合に表示-->
        <div class="media-right" *ngIf="comment.user.uid === currentUser.uid">
          <a href="#" class="icon-rounded">{{comment.initial}}</a>
        </div>
      </div>
      <hr>
      </ng-container>
    </div>
  </section>

  <section>
    <form class="chart-form">
      <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="button">SEND</button>
        </div>
      </div>
    </form>
  </section>
</div>

DOMが長くなったことで表示の一部が崩れたので、CSSを修正します。

src/app/app.component.css
.page { /*更新*/
  max-width: 960px;
  height: 100%;
  margin: 0 auto;
  padding: 10px 0;
  background-color: #fff;
  border-left: 1px solid #DDDDDD;
  border-right: 1px solid #DDDDDD;
  box-shadow: 0 0 15px #DDDDDD;
  overflow: scroll;
}

.page section{ /*追加*/
  margin: 0 10px 30px;
}

.page .page-footer{ /*追加*/
  display: block;
  position: fixed;
  margin: 0;
  padding: 10px;
  bottom: 0;
  height: 55px;
  width: 100%;
  max-width: 958px;
  background-color: #fff;
  border-top: 1px solid #DDDDDD;
}

/*削除
.page .chart-form {
  margin: 20px 0;
}*/
 

ディレクティブの*と括弧[]``()

*ngIfのように、ディレクティブの前に*がついた場合、その=の先にある式はscript文として評価されます。例:*ngIf="comment.user.uid !== current_user.uid"の場合、それぞれのuidが等しい場合にのみ表示される。
一方、同様に他のディレクティブ 内でもscript文として変数や式を利用したい場合は、[]()を使って表現します。例:[style.color]="comment.user.uid !== current_user.uid ? 'red' : 'black'"の場合、それぞれのuidが等しい場合にのみ文字色が赤くなる。

submitイベントで新しいコメントを追加する

addComment関数をAppComponentに追加する

フォームに入力したコメントをチャットに追加するため、addComment関数を実装します。

src/app/app.component.ts
export class AppComponent {
  public content = '';
  public comments = COMMENTS;
  public current_user = CURRENT_USER;

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

submitイベントをHTMLに追加する

Angularは、ビューからデータへ値を渡す時、(click)(submit)のように丸括弧()をつけて表記します。
(この表記はビューからデータへ、一方向だけに送られるということを意味しています。逆にデータをビューへ渡す時は、角括弧[ ]を使って表記します。)

ngModelでcontentを紐付け、入力された値をaddComment関数に渡します。

src/app/app.component.html
  <section>
    <form class="chart-form" (submit)="addComment(content)"><!--addComment()を追加-->
      <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><!--submitに変更-->
        </div>
      </div>
    </form>
  </section>

実行結果

フォームに「コメント テスト」と入力して、SENDボタンをクリックすると、チャットコメントが追加されました。

ezgif-1-e20e8462e8.gif

ソースコード

この時点でのソースコード

18
8
1

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
18
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?