前提・実現したいこと
Angular12
を用いたWebアプリケーションを作ろうとしています。
外部APIをたたいて得られたデータをng2-charts
によりチャートにします。
再びAPIをたたたとき、先ほどのチャートを新しく得られたデータによって再描画したいと考えています。
発生している問題
はじめてAPIをたたいた結果によるチャートの描画を行うことはできています。
もう一度APIをたたいて変数を更新できているのに、チャートの再描画が走らず、前のデータのチャートのままになってしまいます。
以下は一回目のAPIコールの結果です。
このように、住所を入れて検索ボタンを押すと、気温をグラフを作成するのですが、
この状態から住所を変えて、再び検索ボタンを押しAPIコールすると以下のようになります。
データが書き換えられているはずであるのに、チャートの内容が前回のまま引き継がれてしまいます。
該当のソースコード
daily-temp-chart.component.ts
の親コンポーネントで検索を行い、検索結果が@Input()
に渡されます。
親コンポーネントにより渡されるdataSet
の値が変化していることを、ngOnChanges
ライフサイクルメソッドで検知し、データの更新を行うような仕様となっています。
TypeScript
1// daily-temp-chart.component.ts 2import { Component, Input, SimpleChanges } from '@angular/core'; 3import { ChartDataSets, ChartType } from 'chart.js'; 4import { Color, Label } from 'ng2-charts'; 5 6 7@Component({ 8 selector: 'app-daily-temp-chart', 9 templateUrl: './daily-temp-chart.component.html', 10 styleUrls: ['./daily-temp-chart.component.scss'] 11}) 12export class DailyTempChartComponent { 13 14 @Input() dataSet: any; // 親から受け取るAPIコールの結果 15 private datas: number[] = []; // 気温データ格納用 16 private indexs: string[] = []; // 時間格納用 17 private minimam = 0; 18 19 ngOnChanges(changes: SimpleChanges): void { 20 if (changes['dataSet'].currentValue) { 21 let val = changes['dataSet'].currentValue; 22 // データ更新 ここの処理が重たいからか? 23 for (let i = 0; i < val.hourly.length; i++) { 24 this.indexs[i] = (new Date(val.hourly[i].dt * 1000).getHours().toString()); 25 this.datas[i] = +(val.hourly[i].temp - 273.15).toFixed(2); 26 } 27 } 28 } 29 // data 30 public lineChartData: ChartDataSets[] = [ 31 { 32 data: this.datas, 33 label: 'Daily Temp' 34 }, 35 ]; 36 37 // labels name 38 public lineChartLabels: Label[] = this.indexs; 39 40 // options 41 public lineChartOptions = { 42 responsive: true, 43 scales: { 44 yAxes: [{ 45 ticks: { 46 steps: 10, 47 stepValue: 10, 48 min: this.minimam 49 } 50 }] 51 } 52 } 53 54 // Colors 55 public lineChartColors: Color[] = [ 56 { 57 borderColor: 'black', 58 backgroundColor: 'rgba(255,0,255,0.28)', 59 }, 60 ] 61 62 public lineChartLegend = true; // グラフの属性ラベル 63 public lineChartPlugins = []; 64 public lineChartType: ChartType = 'line'; // グラフの種類 65} 66
html
1<!-- daily-temp-chart.component.html --> 2<div id="dailyChart"> 3 <canvas baseChart 4 [datasets]="lineChartData" 5 [labels]="lineChartLabels" 6 [options]="lineChartOptions" 7 [colors]="lineChartColors" 8 [legend]="lineChartLegend" 9 [chartType]="lineChartType" 10 [plugins]="lineChartPlugins"> 11 </canvas> 12</div>
html
1<!-- parent.component.html --> 2<div> 3 <!-- 他のコンポーネントは省略 --> 4 <!-- バインディング部分のみ示す --> 5 <app-daily-temp-chart [dataSet]='dataSet'></app-daily-temp-chart> 6</div>
試したこと
dataSet
変数の中身が更新されているかを、console.log
により確認しました。
以下が一回目のAPIコール後のdataSet
の中身です。
そのまま二回目のAPIコールをしたときの中身です。
これを見る限りでは、dataSet
の中身は更新されているのですが、非同期処理の関係上なのかfor文
が終わる前にチャートを表示してしまっているような気がします。(lat, lonの値を見ると明らか)
ですが、Web上ではなかなかうまい解決方法が見つかりませんでした。
補足情報(FW/ツールのバージョンなど)
説明がわかりにくい個所もあるかと思いますが、よろしくお願いします。
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
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/07/28 12:31