中安拓也のブログ

プログラミングについて書くブログ

Angularがデータの変更を検知してくれないのでChange Detectionを呼ぶ

障害対応でAngularのChange Detectionをコントロールするクラス(ChangeDetectorRef)を使用する機会があったのでメモ

発生した障害

クリックでインクリメントする値と複数のngIfを組み合わせて、アプリの操作方法を説明するチュートリアルを作成していたが、値は正常にカウントアップされているのにngIf(チュートリアル)が切り替わらない...という障害がときどき発生した

  • ソースのイメージ
<!-- クリックするとチュートリアルが切り替わる -->
<div (click)="nextStep()">
    <!-- stepの値が増えてもずっと、tutorial-1だけが表示される障害 -->
    <div class="common-tutorial-img" >
      <div class="tutorial-1" *ngIf="step === 1"></div>
      <div class="tutorial-2" *ngIf="step === 2"></div>
      <div class="tutorial-3" *ngIf="step === 3"></div>
    </div>
</div>

上記のソースのイメージで、発生した障害を説明するとstep変数は1, 2, 3...といった感じにインクリメントされているのに、ずっと<div class="tutorial-1" *ngIf="step === 1"></div>だけが表示されるといった事象がおきた。

対応内容

step変数の値が変更されているのをAngularが検知して再描画してくれないのが原因だと考えたため、step変数の値が増えるたびにChangeDetectorRef#detectChanges()を毎回呼び出して、モデル(step変数)の値が変更されるたびに画面を再描画するように修正した。

終わりに

step変数の値の渡しかたを工夫してあげれば、ChangeDetectorRef#detectChanges()を呼び出さなくても自動でChange Detectionがはしった気がしないでもない

バージョン

  • Angular v4
  • ionic-angular: 3.9.5

参考サイト

https://angular.io/api/core/ChangeDetectorRef

[Angular] コンポーネントを強制的に再描画する方法 │ Web備忘録

日本語訳:Angular 2 Change Detection Explained - Qiita