1

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
              }
          ]
          },

2 Answers 2

2

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}
];

*/
Sign up to request clarification or add additional context in comments.

2 Comments

but what if my values are structured like [{valueA: 1A valueB: 2A}} where each object has multiple values? how would I add that to my final array so I can only have one dataset? @priscillaanjos
Also how could I use this if the labels only accept string values?
1

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
                          }
                      }]
                  }
              }
          }
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.