2
1

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】@ViewChildを使用した際のコンパイルエラー

Last updated at Posted at 2021-07-06

Angularにて、下記記事で紹介されているようなファイル選択ボタンを作りたかった。

環境

  • Angular: 12.0.5
  • TypeScript: 4.2.4
  • エディタ: VSCode

修正前

app.component.html
<button
    mat-raised-button
    color="primary"
    (click)="onClick()">
    <mat-icon>attach_file</mat-icon>
    ファイルを選択
</button>
<input #fileInput type="file" style="display:none;">
app.component.ts
import { Component, ElementRef, ViewChild } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  @ViewChild('fileInput') fileInput: ElementRef;

  onClick(): void {
    this.fileInput.nativeElement.click();
  }
}

こちらで保存すると、コンパイルエラー(VSCode上でもエラーが出る)

error TS2564: Property 'fileInput' has no initializer and is not definitely
 assigned in the constructor.

10   @ViewChild('fileInput') fileInput: ElementRef;
                             ~~~~~~~~~

fileInputに初期化子がなく、コンストラクターで明確に割り当てられていない・・・

解決策

こちらの記事によれば、
TypeScript 2.7 からクラスプロパティの初期化をチェックするstrictPropertyInitializationオプションが導入され、

tsconfigstrictPropertyInitializationオプションを有効にすると、undefinedを許容していないプロパティがプロパティ宣言時あるいはコンストラクタで初期化されていないときにコンパイルエラーになる。

とのこと。そして

@ViewChild@ContentChildrenなどは、クラスの初期化時ではなくコンポーネントのビューツリーの解決時に初期化されるので、strictPropertyInitializationがうまく噛み合わなくなる。

これがコンパイルエラーの原因。

@ViewChild@ContentChildはオプショナルプロパティとして扱うべし

これに言及してくれている記事がほとんどなく解決に苦労しました。ありがとうございます:raised_hands:

修正後

というわけで、修正後のコードはこちら。

app.component.ts
import { Component, ElementRef, ViewChild } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  @ViewChild('fileInput') fileInput?: ElementRef;  // オプショナルプロパティに

  onClick(): void {
    if (this.fileInput !== undefined) {  // 追加
      this.fileInput.nativeElement.click();
    }
  }
}
2
1
0

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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?