質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Angular

Angularは、JavaScriptフレームワークです。AngularJSの後継であり、TypeScriptベースで実装されています。機能ごとに実装を分けやすく、コードの見通しが良いコンポーネント指向です。

Chart.js

Chart.jsは、多様なグラフを組み込めるJavaScriptのライブラリ。折れ線グラフや棒グラフ、円グラフ、レーダーチャートなどのグラフの種類が用意されています。HTML5のCanvasを用いて描画され、マークアップも分かりやすく、簡単に編集することが可能です。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

解決済

1回答

1939閲覧

Angular12でng2-chartsのチャート再更新が行われない

yosse95ai

総合スコア39

Angular

Angularは、JavaScriptフレームワークです。AngularJSの後継であり、TypeScriptベースで実装されています。機能ごとに実装を分けやすく、コードの見通しが良いコンポーネント指向です。

Chart.js

Chart.jsは、多様なグラフを組み込めるJavaScriptのライブラリ。折れ線グラフや棒グラフ、円グラフ、レーダーチャートなどのグラフの種類が用意されています。HTML5のCanvasを用いて描画され、マークアップも分かりやすく、簡単に編集することが可能です。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

0グッド

0クリップ

投稿2021/07/27 17:38

編集2021/07/28 04:13

前提・実現したいこと

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

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

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

発生している問題

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

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

以下は一回目のAPIコールの結果です。

一回目のAPIコール

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

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

2回目の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の中身です。

1回目のAPIコールdataSet

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

2回目のAPIコールdataSet

これを見る限りでは、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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ng2-chartsを利用したことはありませんがdataSetの参照が更新されたタイミングでlineChartDatalineChartLabelsの参照は更新されていないからではないでしょうか。

ts

1 ngOnChanges(changes: SimpleChanges): void { 2 if (changes['dataSet'].currentValue) { 3 let val = changes['dataSet'].currentValue; 4 // データ更新 ここの処理が重たいからか? 5 for (let i = 0; i < val.hourly.length; i++) { 6 this.indexs[i] = (new Date(val.hourly[i].dt * 1000).getHours().toString()); 7 this.datas[i] = +(val.hourly[i].temp - 273.15).toFixed(2); 8 } 9 } 10 // 参照を更新するために以下を追加 11 this.lineChartData = [ 12 { 13 data: this.datas, 14 label: 'Daily Temp' 15 }, 16 ]; 17 }

または変更検知処理を直接呼び出しても良いかもしれません。

ts

1 2 // 追加 3 constructor(private cd: ChangeDetectorRef) {} 4 5 ngOnChanges(changes: SimpleChanges): void { 6 if (changes['dataSet'].currentValue) { 7 let val = changes['dataSet'].currentValue; 8 // データ更新 ここの処理が重たいからか? 9 for (let i = 0; i < val.hourly.length; i++) { 10 this.indexs[i] = (new Date(val.hourly[i].dt * 1000).getHours().toString()); 11 this.datas[i] = +(val.hourly[i].temp - 273.15).toFixed(2); 12 } 13 } 14 // 変更検知を行うために追加 15 this.cd.detectChanges() 16 }

投稿2021/07/28 10:10

編集2021/07/28 10:15
emoyome

総合スコア11

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yosse95ai

2021/07/28 12:31

うまくいきました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問