angulartypescriptchartschart.jsangular9

Chart.JS - Implement multi-bar chart


I implemented Chart.JS in my Angular 9 application. The chart is not rendered as expected.

ngOnInit(): void {
  this.smdashboardservice.fetchSmDashboardData().subscribe(response=>{

    //let data = response.data
    let data = [
      {"label":"Application","sublabel":"Nice","count":2},
      {"label":"Application","sublabel":"poor","count":1},
      {"label":"Channels","sublabel":"Quality","count":2},
      {"label":"Customer Care","sublabel":"support","count":2}
    ]

    this.barChartLabels = Object.keys(data);
    this.barChartLabels.forEach(label => {
      this.barChartData[0].data.push(data[label]['count']);
    });

  })
}

Current code giving chart

enter image description here

But I am expecting like this

enter image description here

Demo here


Solution

  • You need to prepare the datasets which categorize the sublabel.

    Each dataset should contain the values with the length of x-axis category (label), which is 3.

    let labels = [...new Set(data.map((x) => x.label))];
    let subLabels = [...new Set(data.map((x) => x.sublabel))];
    let subLabelDatasets = subLabels.map((x) => {
      let datasets = [];
    
      for (let label of labels) {
        datasets.push(
          data.find((y) => y.label == label && y.sublabel == x)?.count || 0
        );
      }
    
      return {
        label: x,
        data: datasets,
      };
    });
    
    this.barChartLabels = labels;
    this.barChartData = subLabelDatasets;
    

    Demo @ StackBlitz

    Alternative: subLabelDatasets can be simplified as:

    let subLabelDatasets = subLabels.map((x) => ({
      label: x,
      data: labels.map(
        (label) =>
          data.find((y) => y.label == label && y.sublabel == x)?.count || 0
      )
    }));