小ネタです。
Angular Materialを使ったプロジェクトで、ファイル選択input <input type="file" />
を使うときにボタンをmat-buttonにする方法を紹介します。
HTML
<input type="file" style="display: none" #fileInput accept="image/*" (change)="onChangeFileInput()" />
<button mat-raised-button color="primary" class="file-select-button" (click)="onClickFileInputButton()">
<mat-icon>attach_file</mat-icon>
ファイルを選択
</button>
<p class="file-name" *ngIf="!file; else fileName">ファイルが選択されていません</p>
<ng-template #fileName>
<p class="file-name">{{ file?.name }}</p>
</ng-template>
- 1行目: 通常のinputコントロールに対して
#fileInput
という形でテンプレートリファレンスを追加。 また、このコントロールはmat-buttonに置き換える予定なので、display: none
で非表示にする - 2-4行目: inputの代わりになるmat-button、 クリックした際に発火するイベントハンドラを設定
- 7行目以降: 選択したファイル名の表示
TypeScript
import { Component, ViewChild } from '@angular/core'; // ViewChildをimport
// ... 中略 ...
export class FileInputComponent {
@ViewChild('fileInput')
fileInput;
file: File | null = null;
onClickFileInputButton(): void {
this.fileInput.nativeElement.click();
}
onChangeFileInput(): void {
const files: { [key: string]: File } = this.fileInput.nativeElement.files;
this.file = files[0];
}
}
- 1行目: テンプレートリファレンスを使って、コンポーネントのクラス側からinputにアクセスするために
ViewChild
をimportしておく - 4行目: テンプレートリファレンスを使ってinput要素を取得しておく
- 9行目: mat-buttonが押さたイベントをinput要素に伝える処理
- 13行目以降: inputのchangeイベントの発火を受けて、file変数にファイル内容を格納する処理
サンプル
stackblitzにサンプルを用意しました。
https://stackblitz.com/edit/angular-material-file-select