I'm using ng2-charts and I'm trying to build support for drilling down into a chart. It shouldn't be hard, just a matter of handling the click event, then changing the labels and the data and I should be pretty much done. But for some reason, the labels aren't updating properly. Check out this plnkr: http://plnkr.co/edit/YPYdegwj3yLnS42Kbisd?p=preview
When you click 2006 and then click January, everything still functions. I'm only changing the labels at this point, not the data. As soon as I do change the data, things get weird. Near the bottom of src/app.ts, there's this piece of code:
// setTimeout(() => {
// this.barChartData = this.currentNode.bars; // uncomment this first
// }, 0)
Uncomment the second line so that the data is changed and try drilling down into 2006/January again. When clicking 2006, the labels don't get updated. Now uncomment the rest of the setTimeout() and you'll notice that everything works as it should: labels updating, data updating. Beautiful.
But this setTimeout() really should not be necessary. Since it has to do with databinding, I suspect this is an ng2-charts bug and not a chart.js bug.
This appears to be the same issue as encountered with #291, #424, and #630. The error here is 'Label' undefined not 'Data' undefined, but seems to be the same issue: setTimeout() shouldn't be necessary, no doubt, but it's one of the workarounds you can use that are necessary to update the chart. @ViewChild seems to be the most stable and least "hacky" way to fix these issues.
I have a similar issue.
I am getting labels and data from the backend, but only the data is dynamically updated. I am doing this in my subscribe:
let stats = response.data;
let labels = [];
let values = [];
let index = 0;
for(let i in stats){
labels[index] = 'Week ' + stats[i].week;
values[index] = stats[i].deviationCount;
index++;
}
this.chartConfig.data.datasets = [{ data: values }];
this.chartConfig.labels = labels;
I am using one of the example line charts and using some of its default values.
<div style="display: block;">
<canvas baseChart width="400" height="400"
[datasets]="chartConfig.data.datasets"
[labels]="chartConfig.labels"
[options]="chartConfig.options"
[colors]="lineChartColors"
[legend]="lineChartLegend"
[chartType]="chartConfig.type"
(chartHover)="chartHovered($event)"
(chartClick)="chartClicked($event)"></canvas>
</div>
This just renders and chart with no labels, but if I use the example label variable it works:
public lineChartLabels:Array
My this.chartConfig.labels array contains exactly the same number of labels as I have data values (7). I have compared the backend update array to the example array and I cannot see any difference.
What is wrong?
@ChrisWorks Consider trying this :
setTimeout(function () {
this.chartConfig.data.datasets = [{ data: values }];
this.chartConfig.labels = labels;
}, 0);
This should work.
And as said by @JPtenBerge @zbagley, this is just a work around.
The trick is in clearing the label and data array, the below code didnt work for me :(
clearCharts() {
this.barChartLabels= [];
this.barChartData= [
{data: [], label: 'label1'},
{data: [], label: 'label2'}
];
}
However when I changed the way I cleared the data helped me (Using object reference)
clearCharts() {
this.barChartLabels= [];
this.emptyChartData(this.barChartData);
}
emptyChartData(obj) {
obj[0].data = [];
obj[1].data = [];
obj[0].label = 'label1';
obj[1].label = 'label2';
}
@JPtenBerge Were you able to make the chart is back, after navigating in the year 2016?
here is another work around that works on my end just add a condition on the canvas wrapper element
*ngIf="lineChartLabels.length > 0" to redraw the chart.
<div class="chart" *ngIf="lineChartLabels.length > 0">
<canvas baseChart height="114"
[datasets]="lineChartData"
[labels]="lineChartLabels"
[options]="chartOptions"
[chartType]="lineChartType"
[colors]="lineChartColors">
</canvas>
</div>
@juanito-lansangan worked for me thanks!
@juanito-lansangan super!!!
I was already going for the @Viewchild reference to call the .update() method; but your work around is easy and it works! Thanks!
@juanito-lansangan this is nice, but has some not so nice visual flashing effects... any idea to stop that?
@juanito-lansangan neat solution. Thank you.
Also see this similar issue for solution https://github.com/valor-software/ng2-charts/issues/718#issuecomment-471173803
[datasets]="ChartData"
//...other stuff >
and in the component I have a function which update the chart with new data, and then I clone the datasets and re-assign it
drawChart(){
this.ChartData=[{data: this.dataX, label: 'X'}]; // this.dataX has new values from some place in my code
//nothing happened with my chart yet, until I add this lines:
let clone = JSON.parse(JSON.stringify(this.ChartData));
this.ChartData=clone;
//other stuff like labels etc.
}
Use ng4-charts instead. If your label never update after pushing new element to the labelList use this
this.labelList = this.labelList.splice(0) to force re-render
here is another work around that works on my end just add a condition on the canvas wrapper element
*ngIf="lineChartLabels.length > 0" to redraw the chart.<div class="chart" *ngIf="lineChartLabels.length > 0"> <canvas baseChart height="114" [datasets]="lineChartData" [labels]="lineChartLabels" [options]="chartOptions" [chartType]="lineChartType" [colors]="lineChartColors"> </canvas> </div>
chart.js vs 2.7.2 working for me, thank sm!!
here is another work around that works on my end just add a condition on the canvas wrapper element
*ngIf="lineChartLabels.length > 0" to redraw the chart.<div class="chart" *ngIf="lineChartLabels.length > 0"> <canvas baseChart height="114" [datasets]="lineChartData" [labels]="lineChartLabels" [options]="chartOptions" [chartType]="lineChartType" [colors]="lineChartColors"> </canvas> </div>
Its not working for me, i have ng2-charts 2.3.2
Most helpful comment
here is another work around that works on my end just add a condition on the canvas wrapper element
*ngIf="lineChartLabels.length > 0" to redraw the chart.