score:56
Apparently, if you do not modify the original reference to the labels array, it seems to work, at least for me. I mean, if you want a completely different set of labels, you should do something like this:
In the template:
<canvas baseChart
[datasets]="lineChartData"
[labels]="lineChartLabels"
[options]="lineChartOptions"
[chartType]="'line'"></canvas>
In the ts component:
this.lineChartLabels.length = 0;
for (let i = tempLabels.length - 1; i >= 0; i--) {
this.lineChartLabels.push(tempLabels[i]);
}
Or, using new ECMAScript syntax:
this.lineChartLabels.length = 0;
this.lineChartLabels.push(...tempLabels);
The key is maybe the this.lineChartLabels.length = 0;
statement, which practically 'empties' your array by setting its length to 0, without modifying the reference.
Hope this helps!
score:0
Since I didn't manage to get one of the above solutions to work properly, I want to contribute my solution, in case someone stumbles across this post and also got stuck with the present approaches.
I have the HTML similar to @mustafa918:
<div>
<canvas #canvas id="canvas"
baseChart [datasets]="lineChartData"
[labels]="lineChartLabels"
[colors]="lineChartColors"
[options]="lineChartOptions"
[chartType]="lineChartType"
[legend]="lineChartLegend"
(chartHover)="chartHovered($event)"
(chartClick)="chartClicked($event)">
</canvas>
</div>
And for the initialisation of the charts data in typescript i have:
public lineChartData: Array<any> = [
{ data: this.heights, label: 'Heights History', type: 'line', fill: false},
{ data: this.widths, label: 'Widths History', type: 'line', fill: false }];
And for me it worked only by setting the data and labels at the same time and don't use chart.update() - chart is the reference to the BaseChartDirective.
I loaded the respective data and labels beforehand, so that in this.heights, this.width and this.lineChartLabels are corresponding data.
E.g. : The entries on heights[i], widths[i] and lineChartLabels[i] match with the element in my elementArray at index i => element ={ "height":30, "width":20, "label":"box"}
setDatasets() {
//store data in chart references
var arrHeights = [];
for (var i in this.heights) {
arrHeights.push({ x: this.lineChartLabels[i], y: this.heights[i] });
}
var arrWidths= [];
for (var i in this.widths) {
arrWidths.push({ x: this.lineChartLabels[i], y: this.widths[i] });
}
this.lineChartData[0].data = arrHeights;
this.lineChartData[1].data = arrWidths;
}
I hope this helps someone :) Good Luck!
score:0
Today i struggled with similar problem, it appears there is a huge bug inside the updateChartData function of ng2-charts library version 1.6.0.
Here is the original function:
updateChartData = function (newDataValues) {
if (Array.isArray(newDataValues[0].data)) {
this.chart.data.datasets.forEach(function (dataset, i) {
dataset.data = newDataValues[i].data;
if (newDataValues[i].label) {
dataset.label = newDataValues[i].label;
}
});
}
else {
this.chart.data.datasets[0].data = newDataValues;
}
}
As you can see this updates only the data and the label, but all other properties are left behind. In my case i wanted to update also the pointBorderColor so i decided to override this.
First i get a reference to the ng2-charts library:
import { BaseChartDirective } from 'ng2-charts';
@ViewChild(BaseChartDirective) chart: any;
It is very important the type is "any", because otherwise typescript will not allow me to override a private function.
Then i fix the bug in the function and override it in afterVIew init:
ngAfterViewInit(){
if (this.chart) {
this.chart.updateChartData = function (newDataValues) {
if (Array.isArray(newDataValues[0].data)) {
this.chart.data.datasets.forEach(function (dataset, i) {
dataset.data = newDataValues[i].data;
if (newDataValues[i].pointBorderColor) {
dataset.pointBorderColor = newDataValues[i].pointBorderColor;
}
if (newDataValues[i].label) {
dataset.label = newDataValues[i].label;
}
});
}
else {
this.chart.data.datasets[0].data = newDataValues;
}
}.bind(this.chart);
}
}
score:0
Based on above answers, I extended this function and everything works fine now!
TS Code:
Declare : import { BaseChartDirective } from 'ng2-charts';
@ViewChild(BaseChartDirective) chart: BaseChartDirective;
public lineChartData: ChartDataSets[] = [
{ data: [0, 0, 0, 0, 0, 0, 0], label: 'Data 1' },
{ data: [0, 0, 0, 0, 0, 0, 0], label: 'Data 2' }
];
public lineChartLabels: Label[] = ['Label1', 'Label2', 'Label3', 'Label4',
'Label5', 'Label6';
TS Function:
refresh_chart(){
setTimeout(() => {
if (this.chart && this.chart.chart && this.chart.chart.config) {
this.chart.chart.config.data.datasets.forEach(x => {
x.data = [];
});
let index = 0;
this.chart.chart.config.data.datasets.forEach(x => {
x.data = this.lineChartData[index].data;
index++;
});
this.chart.chart.update();
}
}, 500);
}
HTML Code:
<canvas baseChart [datasets]="lineChartData" class="canvas-wh" [labels]="lineChartLabels"
[options]="lineChartOptions" [colors]="lineChartColors" [legend]="lineChartLegend"
[chartType]="lineChartType" [plugins]="lineChartPlugins">
score:0
For me, it worked only after using ViewChildren and not ViewChild.
TS:
@ViewChildren('baseLineChart1') chart !: QueryList<BaseChartDirective>;
this.chart.forEach((child) => { child.update() })
HTML:
<canvas class="card-line-chart" baseChart #baseLineChart1>
score:1
There is another way to do it:
In your HTML you have
<canvas baseChart
[datasets]="ChartData"
//...other stuff >
</canvas>
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.
}
this works for me, hope it works for you too
score:1
I was able to fix this issue by turning the handler into an arrow function
export class HistogramChartComponent implements OnInit {
constructor(private dataService: MyFruitService ) { }
barChartOptions: ChartOptions = { responsive: true };
barChartLabels: Label[] = ['Apple', 'Banana', 'Kiwifruit', 'Blueberry', 'Orange', 'Grapes'];
barChartType: ChartType = 'bar';
barChartLegend = true;
barChartPlugins = [];
barChartData: ChartDataSets[] = [
{ data: [45, 37, 60, 70, 46, 33], label: 'Best Fruits' }
];
ngOnInit() {
this.dataService
.getDocument("Foobar")
.subscribe(this.handleResponse);
}
handleResponse = (doc: MyFruitDocument) => {
console.log('document: ', doc);
let labels = doc.dataPoints.map(p => p.fruitName);
let data = { data: doc.dataPoints.map(p => p.value), label: 'Best Fruits' };
this.barChartLabels = labels;
this.barChartData = [ data ];
}
}
score:1
I have also faced this issue when trying to update the labels, (specifically when trying to send a shorter array), And this solved it:
@ViewChild(BaseChartDirective) chart!: BaseChartDirective;
and then, when updating the labels:
this.chart.chart!.config.data.labels = [...]
No need to call the update() method.
score:2
This is an issue in the library ng2-charts, to resolve it I have cloned the github of ng2-charts in my app directory and have done following steps :
npm install
- in appmodule import ng-2charts.ts from src directory.
- add this
updateChartLabels
function to chart.ts file - call it in the
onChanges
function.
public ngOnChanges(changes: SimpleChanges): void { if (this.initFlag) {
if(changes.hasOwnProperty('labels')){
console.log('labels changes ...');
this.updateChartLabels(changes['labels'].currentValue);
}
//..
//...
}
private updateChartLabels(newLabelsValues: string[] | any[]): void {
this.chart.data.labels = newLabelsValues;
}
score:2
This is an issue with the current ng2-charts library.
Try the new ng4-charts library which has fixed this issue.
score:2
For those looking for a walk around, for now you can put your labels and data in an object and put that object in an array and just loop through the array in your html. This will redraw the element every time your array changes.
in your type script every time there's a change.
data = [...]; labels = [...]; chartArray = [{data , labels }]
in your html
<canvas *ngFor="let chartData of chartArray " [datasets]="chartData.data" [labels]="chartData.labels" > </canvas>
score:4
Using BaseChartDirective i did chart update and it served the purpose. Sample below:
import { BaseChartDirective } from 'ng2-charts';
inside the class add as below
@ViewChild(BaseChartDirective) chart: BaseChartDirective;
While you have the values to be changed, add as below
this.chart.ngOnChanges({});
score:5
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';
}
```
score:8
Using BaseChartDirective i did chart update and it served the purpose. Sample below:
import { BaseChartDirective } from 'ng2-charts/ng2-charts';
inside the class add as below
@ViewChild(BaseChartDirective) chart: BaseChartDirective;
While you have the values to be changed, add as below
setTimeout(() => {
if (this.chart && this.chart.chart && this.chart.chart.config) {
this.chart.chart.config.data.labels = this.labels_pie;
this.chart.chart.update();
}
});
score:10
Like Deyd pointed out before, this is caused by a combination of Angular 2+'s change detection and a bug in ng2-charts.
According to my own observations (correct me if I'm wrong), Angular merges several changes within a very short timeframe into a single collection (changes: SimpleChanges
) when ngOnChanges
is called.
Unfortunately, ng2-charts only checks if the dataset has been changed with this collection and updates it. Otherwise it completely rebuilds the entire chart. However, because of the way the change detection works, more than one property might have been changed. Then, only the dataset gets updated even if the labels and possibly other properties have been updated as well. See ngOnChanges
in ng2-charts:
valor-software/ng2-charts/src/charts/charts.ts
And if you don't want to have a separate copy of ng2-charts in your app and fix the problem yourself, a possible workaround for this problem is to set the dataset with a short delay using JavaScript's built-in function setTimeout(callback: () => void, delay: number)
.
Before:
@Component({
selector: 'app-root',
template: `
<select (change)="onChange($event.target.value)">
<option value="" disabled selected>Select your option</option>
<option value="0">Option 0</option>
<option value="1">Option 1</option>
</select>
<canvas baseChart
chartType="bar"
[datasets]="barChartData"
[labels]="barChartLabels"
[colors]="barChartColors">
</canvas>
`
})
export class AppComponent implements OnInit {
chartData: string[];
chartLabels: string[];
chartColors: string[];
onChange(id: string) {
getFromApiById(id)
.then(result => this._setChart(result.data, result.labels, result.colors));
}
private _setChart(data: string[], labels: string[], colors: string[]) {
this.chartData = data;
this.chartLabels = labels;
this.chartColors = colors;
}
}
After:
@Component({
selector: 'app-root',
template: `
<select (change)="onChange($event.target.value)">
<option value="" disabled selected>Select your option</option>
<option value="0">Option 0</option>
<option value="1">Option 1</option>
</select>
<canvas baseChart
chartType="bar"
[datasets]="barChartData"
[labels]="barChartLabels"
[colors]="barChartColors">
</canvas>
`
})
export class AppComponent implements OnInit {
chartData: string[];
chartLabels: string[];
chartColors: string[];
onChange(id: string) {
getFromApiById(id)
.then(result => this._setChart(result.data, result.labels, result.colors));
}
private _setChart(data: string[], labels: string[], colors: string[]) {
this.chartLabels = labels;
this.chartColors = colors;
setTimeout(() => {
this.chartData = data;
}, 50);
}
}
score:17
Recently i had to use ng2-charts and i was having a very big issues with updating my data untill i found this sollution:
<div class="chart">
<canvas baseChart [datasets]="datasets_lines" [labels]="labels_line" [colors]="chartColors" [options]="options" [chartType]="lineChartType">
</canvas>
</div>
and here what i have in my component :
import { Component, OnInit, Pipe, ViewChild, ElementRef } from '@angular/core';
import { BaseChartDirective } from 'ng2-charts/ng2-charts';
@Component({
moduleId: module.id,
selector: 'product-detail',
templateUrl: 'product-detail.component.html'
})
export class ProductDetailComponent {
@ViewChild(BaseChartDirective) chart: BaseChartDirective;
private datasets_lines: { label: string, backgroundColor: string, borderColor: string, data: Array<any> }[] = [
{
label: "Quantities",
data: Array<any>()
}
];
private labels_line = Array<any>();
private options = {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
};
constructor() { }
ngOnInit() {
this.getStats();
}
getStats() {
this._statsService.getStatistics(this.startDate, this.endDate, 'comparaison')
.subscribe(
res => {
console.log('getStats success');
this.stats = res;
this.labels_line = this.getDates();
this.datasets_lines = [];
let arr: any[];
arr = [];
for (let stat of this.stats) {
arr.push(stat.quantity);
}
this.datasets_lines.push({
label: 'title',
data: arr
});
this.refresh_chart();
},
err => {
console.log("getStats failed from component");
},
() => {
console.log('getStats finished');
});
}
refresh_chart() {
setTimeout(() => {
console.log(this.datasets_lines_copy);
console.log(this.datasets_lines);
if (this.chart && this.chart.chart && this.chart.chart.config) {
this.chart.chart.config.data.labels = this.labels_line;
this.chart.chart.config.data.datasets = this.datasets_lines;
this.chart.chart.update();
}
});
}
getDates() {
let dateArray: string[] = [];
let currentDate: Date = new Date();
currentDate.setTime(this.startDate.getTime());
let pushed: string;
for (let i = 1; i < this.daysNum; i++) {
pushed = currentDate == null ? '' : this._datePipe.transform(currentDate, 'dd/MM/yyyy');
dateArray.push(pushed);
currentDate.setTime(currentDate.getTime() + 24 * 60 * 60 * 1000);
}
re
turn dateArray;
}
}
i m sure this is the right way to do it, and hope this would be helpfull
Source: stackoverflow.com
Related Query
- Angular 8 and ng2 charts - Updating labels and data
- ng2-charts update labels and data
- charts labels and data with php arrays
- Update charts in chartjs and angular
- Chart JS: Ignoring x values and putting point data on first available labels
- ChartJS (React) Line Chart - How to show single tooltip with data and labels from 3 (multiple) dataset?
- How to achieve the best possible performance with mutable data and real-time charts in React?
- In Chart.js >3.0, on axis of type time, how to show labels and ticks only for existing data points (make labels reflect data)?
- Setting Common labels and background color common for all the charts in ChartJs
- ng2-charts and annotation plugin: annotations not visible after data update
- How do I customize y-axis labels and randomly pick the value from the data range for x-axis in Chart js
- Charts js and laravel: Render chart after passing in json data
- Chart.js and Angular 8 - Dynamically updating Chart.js labels and data from *ngfor
- ChartJS have xAxes labels match data source
- Charts.js destroy previous data and update
- Angular6 and ng2-charts does not display any charts when i fill data from webservice
- Charts JS: Doughnut chart and hiding tooltip for specific data index within each dataset
- Importing JSON to data and labels for chart.js
- chartjs: doughnut graph onHover get labels and data
- Loop through multiple rows as labels and data in chart.js and PHP
- ChartJS AJAX load labels and data
- how to write labels along with data on top and bottom of each stack in bar chart
- Chart.js, increase space between bars and its labels when increasing the charts width
- How to render multiple Chart.JS charts on the same page with AJAX data and variables
- Update Chart JS data dynamically and add new data, remove old data to create timeline "like" chart
- How can I process json file and display some data in form of charts in django
- I need a PHP query to grab data from the database and use in my bar charts for results
- Unable to pass on data from json file to labels and datasets in chart.js
- Loading and updating dynamic charts with dynamic data (chart.js)
- Chart.js displaying each letter of label and data as a single value on chart. The data and labels provided are arrays
More Query from same tag
- how to display last x float number value in chartjs
- ChartJS not updating
- Chart.js; Chart is not showing time and imported data.
- show name on yaxis in chart.js
- Chartjs xaxes tick min
- When I try to include the chart.js and angular chartjs files, I get: ReferenceError: require is not defined
- Chart not displaying from JSON data
- ChartNew.js - Remove/Hide zero label from Pie Chart
- How to show the data labels without hovering the mouse on the bubbles
- How do you make a progressive line chart with time as the X axis?
- Chartjs : showLine depending on value
- generateLegend() Chart.JS V2
- save my chart.js output to an image
- Query result into array in Laravel 6
- Points cut at half at the edges of top and bottom, at chartjs
- Chart.js core.js:6162 ERROR Error: "line" is not a registered controller
- Overlay loading indicator before data and charts are loaded
- ChartJS get data from Controller
- Chat.js, Codeigniter and MySQL. Something wrong on recover data
- Chart.js - get x-axis label (or index) in onHover event
- How to get bar chart width in pixel
- ng2-charts / chart.js - How to set doughnut/pie chart color on specific labels programatically?
- Chart.js V2 line chart missing point
- Image-Chart ChartJs Ticks Callback not Working?
- How to plot a line chart in ChartJS?
- gap between half doughnut chart and container div
- Make arbitrary line dashed
- import Json formatted values to create bar charts with Chart.js
- Chart.js line chart tooltip shows wrong label when line doesn't start at first label
- How can I express this element?