I am using Angular to show a basic column chart. The idea is to show how many data entries was created by different nodes (This will be received from a web server, but I have removed that code for simplicity for now)
I start with showing two basic columns. Then on a button press I change the series so that it only has one entry. In this case, the first column changes and shows the new data, but the second column stays there, showing the old data even though the series has been completely changed. (The update method in TS file)
In the second case, when I add multiple data entries, only the newest two are shown as columns.
My question is how can I change this code to dynamically change the number of columns based on the entries in the series object? I need this to work effectively since I will never know beforehand how many columns there needs to be as this will be sent from a webservice.
.TS file
import { Component, OnInit } from '@angular/core'; import * as Highcharts from 'highcharts'; import { AuthService } from '../../../auth/auth.service'; @Component({ selector: 'app-widget-area', templateUrl: './area.component.html', styleUrls: ['./area.component.scss'] }) export class AreaComponent implements OnInit { series = []; chartOptions: any; Highcharts = Highcharts; updateFromInput = false; constructor(public authService: AuthService) { } ngOnInit(): void { this.myChart(); } myChart(){ this.chartOptions = { chart: { type: 'column' }, title: { text: 'Total entries by each node' }, xAxis: { type: 'category', }, yAxis: { title: { text: 'total entries' } }, tooltip: { split: false, valueSuffix: ' Entries' }, plotOptions: { line: { dataLabels: { enabled: false }, enableMouseTracking: true } }, series: [{ name: 'Node 1', data: [22] }, { name: 'Node 2', data: [16] }] }; setTimeout(() => { window.dispatchEvent( new Event('resize') ); },300); } update(){ for (let i = 0; i< this.site.nodes.length; i++){ this.series.push({name: 'Node ' + (i+1), data: [3]}); } this.chartOptions.series = this.series; this.updateFromInput = true; } }
HTML file
<highcharts-chart [Highcharts]="Highcharts" [options]="chartOptions" style="width: 100%; height: 400px; display: block;" [(update)]="updateFromInput"> </highcharts-chart> <button (click)="update()">Add</button>
If the problem is unclear, I can edit the post to add screenshots?
Thanks in advance
Advertisement
Answer
I found the solution, it is actually very simple.
Firstyl, this needs to be included at the beginning.
chartOptions: any; Highcharts: typeof Highcharts = Highcharts; chartRef: Highcharts.Chart; chartCallback: Highcharts.ChartCallbackFunction = (chart) => { this.chartRef = chart; };
And in the HTML you change it like this:
<highcharts-chart [Highcharts]="Highcharts" [options]="chartOptions" style="width: 100%; height: 400px; display: block;" [(update)]="updateFromInput" [callbackFunction]="chartCallback"> </highcharts-chart>
This way you can have a handle on the chart.
Secondly, to dynamically remove old data and show new data with an unknown number of columns a couple of things needs to happen.
- Remove all the series from the chart.
- Clear the series object.
- Add the number of series you will need.
- Push the data into the series object
- Assign the series object back to the chart’s series data.
This can be seen in the function I wrote below. Note that this function is called when new data arrives from the server.
update(){ this.removeAll();//remove all the series from the chart this.series = [];//clear die series object //this for loop creates the new number of series and then populates the series object for (let i = 0; i< dataFromServer.length; i++){ this.chartRef.addSeries({ type: 'column', name: 'array', data: [0] }, false); this.series.push({name: dataFromServer[i].name, data: [dataFromServer[i].data]}); } this.chartOptions.series = this.series; this.updateFromInput = true; } removeAll(){ while (this.chartRef.series.length) { console.log(this.chartRef.series[0]); this.chartRef.series[0].remove(); } }