Reputation: 367
I'm using Chart.JS to make a bar chart, but I'm having issues using two JSON objects that I created to make the chart dynamic. I'm not sure of how I should do this but the objects can change values and I want to make the chart support that.
This is my object for labels:
0: {labelName: "Plan Miles"}
1: {labelName: "Actual Miles"}
2: {labelName: "Route Variance"}
and I have a similar object for my data sets.
The object values can be any number so I want to make my chart dynamic to support that.
What can I change in my code to make that happen?
I want to remove the second and third datapoint and only have one dataset that will support multiple bars in the chart. So I would like to loop or map through both the label JSON object and data JSON object to make the chart.
charts.component.ts
export class ChartsComponent implements OnInit {
canvas: any;
ctx: any;
ChartData: any;
labelNames: any;
constructor() {}
ngOnInit(): void {
// Charts
this.canvas = document.getElementById('viewChart');
this.ctx = this.canvas.getContext('2d');
this.ChartData = JSON.parse(localStorage.getItem('ChartData'));
const data = this.ChartData;
//Label Object for Chart
this.labelNames = JSON.parse(localStorage.getItem('LabelNames'));
const labelNames = this.labelNames;
const labelObject = [];
// tslint:disable-next-line: prefer-for-of
for(let i = 0; i < labelNames.length; i++) {
const obj = labelNames[i].propertyName;
labelObject.push({labelName: obj});
}
const newLabelObject = labelObject.slice(3, 5 + 1)
console.log('Labels: ', newLabelObject);
// tslint:disable-next-line: only-arrow-functions
const barLabel = newLabelObject.map(function (e) {
return e[1];
})
// tslint:disable-next-line: only-arrow-functions
const driverLabel = data.map(function (e: any[]) {
return e[1];
});
// tslint:disable-next-line: only-arrow-functions
const firstDataPoint = data.map(function (e: any[]) {
return e[3];
});
// tslint:disable-next-line: only-arrow-functions
const secondDataPoint = data.map(function (e: any[]) {
return e[4];
});
// tslint:disable-next-line: only-arrow-functions
const thirdDataPoint = data.map(function (e: any[]) {
return e[5];
});
const viewChart = new Chart(this.ctx, {
type: 'bar',
data: {
labels: driverLabel,
datasets: [
{
label: `newLabelObject`,
data: firstDataPoint,
backgroundColor: 'rgb(34, 167, 240)',
borderWidth: 1
},
{
label: 'Actual Miles',
data: secondDataPoint,
backgroundColor: 'rgb(240, 52, 52)',
borderWidth: 1
},
{
label: 'Route Variance',
data: thirdDataPoint,
backgroundColor: 'rgba(254, 241, 96, 1)',
borderWidth: 1
}
]
},
Upvotes: 1
Views: 1839
Reputation: 161
The chart.js documentation is probably the best resource in terms of structuring the data for input. From what I understand of your question, you want to toggle between bar graphs in the same chart right? I put together a little stackblitz example of using chart.js in angular to do this. Basically, the chart configuration object defines what gets drawn. This needs to be swapped depending on the data you want to chart and re-rendered. Hope this is helpful / relevant. Apologies if I misunderstood your question.
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { Chart } from 'chart.js';
const dataset1 = {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
}]
};
const dataset2 = {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of People',
data: [3, 5, 2, 12, 19, 3],
}]
};
@Component({
selector: 'app-chart',
templateUrl: './chart.component.html',
styleUrls: ['./chart.component.css']
})
export class ChartComponent implements OnInit {
chart: Chart;
@ViewChild('graph', { static: true })
graph: ElementRef;
ctx: CanvasRenderingContext2D;
currentDataSet = dataset1;
constructor() {}
ngOnInit() {
this.ctx = (<HTMLCanvasElement>this.graph.nativeElement).getContext(
'2d',
);
this.renderChart();
}
renderChart(){
this.chart = new Chart(this.ctx, this.chartConfig);
}
pick(dataSet){
this.currentDataSet = dataSet === 1 ? dataset1 : dataset2;
this.renderChart();
}
get chartConfig(): Chart.ChartConfiguration {
return {
type: 'bar',
data: this.currentDataSet,
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
}
}
}
Upvotes: 1
Reputation: 106
if posible, I think would be better if you used a version of chart that is totally compatible with your version of Angular, like:
But if you realy need to use this version, you could create a array with both values and iterate this array to create your values:
let labels = [{label: "A"}, {label: "B"}, {label: "C"}, {label: "D"}, {label: "E"}];
let values = [{value: 1}, {value: 2}, {value: 3}, {value: 4}, {value: 5}];
let finalArray = [];
labels.forEach((currentLabel, index) => {
finalArray.push({ label: currentLabel.label, value: values[index].value});
});
/* finalArray will be:
[
{label: "A", value: 1}
{label: "B", value: 2}
{label: "C", value: 3}
{label: "D", value: 4}
{label: "E", value: 5}
];
*/
Upvotes: 2