JavaScript
form
angular

【Angular】NgFormを用いて画像のアップロードとPreview表示をする

こんにちは
昨日、画像のアップロードとPreview表示について記事を書きました。
https://qiita.com/TakahitoNakashima/items/354ebd4ceee90bf01696
その部分について、本来はAngularが用意をしている「NgFormを用いるべきだろう」と感じたので、その方法での実装へ変えました。
おそらく、これが一般的なやり方なのではないかと考えています。

ゴール

・無理やり用意した投稿フォームを、NgFormを用いた形へ書き換える

やったこと

・以下2つのページを参考にNgFormへの書き換えを行う
https://angular.jp/guide/forms
https://angular.jp/api/forms/NgForm

詰まったこと

・model.contents , model.fileに値が入らなかった
 → name属性を定義していなかったため。
  以下の2つは必須です。
   ・"ngForm"を読み込ませる
   ・name属性を定義する

以下、before・afterのソースコード

【before】

content-main.component.html
<div class="home-tweet-box tweet-box-component tweet-user">
    <input class="tweet-input" [(ngModel)]="newTweetContents" placeholder="いまどうしてる?">
    <button (click)="setTweetContents(newTweetContents)">ツイート</button>
    <input type='file' accept="image/*" (change)="onChangeInput($event)">
</div>
<img [src]=imageSrc alt="" />
content-main.component.ts
imageSrc = '';
reader = new FileReader();

onChangeInput(evt) {
 const file = evt.target.files[0];
 this.reader.onload = ((e) => {
   this.imageSrc = e.target['result'];
 });
 this.reader.readAsDataURL(file);
}

【after】

content-main.component.html
<app-tweet-form></app-tweet-form>
tweet-form.component.html
<div class="timeline-tweet-box">
  <div class="home-tweet-box tweet-box-component tweet-user">
    <form (ngSubmit)="onSubmit()" #tweetForm="ngForm">
      <div class="form-group">
        <input type='text' class="tweet-input form-control" [(ngModel)]="model.contents" #contents="ngModel" name="contents" placeholder="いまどうしてる?">
        <label class='choice-image'>
          +
          <input type='file' class="form-control" accept="image/*" [ngModel]="model.file" #file="ngModel" name="file"  (change)="onChangeInput($event)" style="display:none;">
        </label>
        <button type='submit' class="tweet-button" (click)="setTweetContents(); tweetForm.reset()">ツイート</button>
      </div>
    </form>
  </div>
  <div *ngIf="fileUrl" class="preview-image">
    <img [src]=fileUrl alt="" />
  </div>
</div>
tweet-form.component.ts
model = new TweetContents(1, '@Taka', '' , '');
  reader = new FileReader();
  fileUrl = '';
  submitted = false;

  constructor(private tweetContentsService: TweetContentsService) { }

  ngOnInit() {
  }

  onSubmit() { this.submitted = true; }

  setTweetContents(): void {
    if (this.model.contents) {
      this.tweetContentsService.setTweetContents(this.model.contents, this.fileUrl);
      this.prepareNewTweet();
    }
  }

  private prepareNewTweet() {
    this.model = new TweetContents(1, '@taka', '', '');
  }

  onChangeInput(evt) {
    const file = evt.target.files[0];
    this.reader.onload = ((e) => {
      this.fileUrl = e.target['result'];
    });
    this.reader.readAsDataURL(file);
  }

まとめ

きれいになったと思われる。

読んでいただいて、ありがとうございました。