78440


### 前提・実現したいこと

`Angular12`を用いたWebアプリケーションを作ろうとしています。

外部APIをたたいて得られたデータを`ng2-charts`によりチャートにします。

再びAPIをたたたとき、先ほどのチャートを新しく得られたデータによって再描画したいと考えています。

### 発生している問題

はじめてAPIをたたいた結果によるチャートの描画を行うことはできています。

もう一度APIをたたいて変数を更新できているのに、チャートの再描画が走らず、前のデータのチャートのままになってしまいます。

以下は一回目のAPIコールの結果です。  
[![APICALL1](https://i.stack.imgur.com/Vcqqv.png)](https://i.stack.imgur.com/Vcqqv.png)

このように、住所を入れて検索ボタンを押すと、気温をグラフを作成するのですが、

この状態から住所を変えて、再び検索ボタンを押しAPIコールすると以下のようになります。

[![APICALL2](https://i.stack.imgur.com/pNyy9.png)](https://i.stack.imgur.com/pNyy9.png)

データが書き換えられているはずであるのに、チャートの内容が前回のまま引き継がれてしまいます。

### 該当のソースコード

`daily-temp-chart.component.ts`の親コンポーネントで検索を行い、検索結果が`@Input()`に渡されます。

親コンポーネントにより渡される`dataSet`の値が変化していることを、`ngOnChanges`ライフサイクルメソッドで検知し、データの更新を行うような仕様となっています。

[code]

    // daily-temp-chart.component.ts
    import { Component, Input, SimpleChanges } from '@angular/core';
    import { ChartDataSets, ChartType } from 'chart.js';
    import { Color, Label } from 'ng2-charts';
    
    
    @Component({
      selector: 'app-daily-temp-chart',
      templateUrl: './daily-temp-chart.component.html',
      styleUrls: ['./daily-temp-chart.component.scss']
    })
    export class DailyTempChartComponent {
    
      @Input() dataSet: any;  // 親から受け取るAPIコールの結果
      private datas: number[] = [];  // 気温データ格納用
      private indexs: string[] = []; // 時間格納用
      private minimam = 0;
    
      ngOnChanges(changes: SimpleChanges): void {
        if (changes['dataSet'].currentValue) {
          let val = changes['dataSet'].currentValue;
          // データ更新 ここの処理が重たいからか？
          for (let i = 0; i < val.hourly.length; i++) {
            this.indexs[i] = (new Date(val.hourly[i].dt * 1000).getHours().toString());
            this.datas[i] = +(val.hourly[i].temp - 273.15).toFixed(2);
          }
        }
      }
      // data
      public lineChartData: ChartDataSets[] = [
        {
          data: this.datas,
          label: 'Daily Temp'
        },
      ];
    
      // labels name
      public lineChartLabels: Label[] = this.indexs;
    
      // options
      public lineChartOptions = {
        responsive: true,
        scales: {
          yAxes: [{
            ticks: {
              steps: 10,
              stepValue: 10,
              min: this.minimam
            }
          }]
        }
      }
    
      // Colors
      public lineChartColors: Color[] = [
        {
          borderColor: 'black',
          backgroundColor: 'rgba(255,0,255,0.28)',
        },
      ]
    
      public lineChartLegend = true; // グラフの属性ラベル
      public lineChartPlugins = [];
      public lineChartType: ChartType = 'line'; // グラフの種類
    }
    
    
[/code]

[code]

    <!-- daily-temp-chart.component.html -->
    <div id="dailyChart">
      <canvas baseChart
        [datasets]="lineChartData"
        [labels]="lineChartLabels"
        [options]="lineChartOptions"
        [colors]="lineChartColors"
        [legend]="lineChartLegend"
        [chartType]="lineChartType"
        [plugins]="lineChartPlugins">
      </canvas>
    </div>
    
[/code]

[code]

    <!-- parent.component.html -->
    <div>
      <!-- 他のコンポーネントは省略 -->
      <!-- バインディング部分のみ示す -->
      <app-daily-temp-chart [dataSet]='dataSet'></app-daily-temp-chart>
    </div>
    
[/code]

### 試したこと

`dataSet`変数の中身が更新されているかを、`console.log`により確認しました。

以下が一回目のAPIコール後の`dataSet`の中身です。

[![APICALL1-console](https://i.stack.imgur.com/eh3Pa.png)](https://i.stack.imgur.com/eh3Pa.png)

そのまま二回目のAPIコールをしたときの中身です。

[![APICALL2-console](https://i.stack.imgur.com/phT5n.png)](https://i.stack.imgur.com/phT5n.png)

これを見る限りでは、`dataSet`の中身は更新されているのですが、非同期処理の関係上なのか`for文`が終わる前にチャートを表示してしまっているような気がします。(lat,
lonの値を見ると明らか)

ですが、Web上ではなかなかうまい解決方法が見つかりませんでした。

### 補足情報（FW/ツールのバージョンなど）

説明がわかりにくい個所もあるかと思いますが、よろしくお願いします。

[code]

    WSL: Ubuntu-20.04
    Node: 14.17.1
    npm: 6.14.13
    Angular CLI: 12.1.0
    typesctipt: 4.3.4
    --------------------npm packages
    chart.js: 2.9.3
    ng2-charts: 2.4.2
    
[/code]

回答が得られなかったのでテラテイルでも同様の質問をしています。  
<https://teratail.com/questions/351563>


CC BY-SA 4.0
2021-07-28T04:09:32.123
78438
2021-07-28T12:07:48.127
2021-07-28T12:07:48.127
47477
47477
question
typescript 非同期 angular
Angular12でng2-chartsのチャート再更新が行われない


lineChartData内の `data` が更新されたと検知されていないと思われます

再代入を試してください

[code]

    ngOnChanges(changes: SimpleChanges): void {
        if (changes['dataSet'].currentValue) {
          let val = changes['dataSet'].currentValue;
          for (let i = 0; i < val.hourly.length; i++) {
            this.indexs[i] = (new Date(val.hourly[i].dt * 1000).getHours().toString());
            this.datas[i] = +(val.hourly[i].temp - 273.15).toFixed(2);
          }
          // 追加
          this.lineChartData = [
                {
                      data: this.datas,
                      label: 'Daily Temp'
                },
          ];
        }
    }
    
[/code]


CC BY-SA 4.0
2021-07-28T05:59:25.413
78440
2021-07-28T05:59:25.413
298
78438
answer