angulargraphchart.jsbar-chartng2-charts

Is it possible to create a graph in which a single broad bar contains multiple bars in Angular?


I want to create a graph like this graph of single bar containing multiple bars

I haven't been able to find a solution.

I asked ChatGPT for the solution. The code it gave out did not work even after trying to make it work. At the end of implementation graph was empty. There were no bars on it. Solution was dependent on 2 libraries ng2-charts@4.1.1 chart.js@4.3.0

Code attempted:

npm install ng2-charts@4.1.1 chart.js@4.3.0

#app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { NgChartsModule } from 'ng2-charts';

@NgModule({
  declarations: [
    // other components
  ],
  imports: [
    BrowserModule,
    NgChartsModule 
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }


#html file
<div style="display: block;">
<canvas
  baseChart
  [data]="barChartData"
  [labels]="barChartLabels"
  [options]="barChartOptions"
  [type]="barChartType"
  [legend]="true">
</canvas>
</div>

#component
import { Component } from '@angular/core';

@Component({
  selector: 'app-error-chart',
  templateUrl: './error-chart.component.html',
  styleUrls: ['./error-chart.component.css']
})
export class ErrorChartComponent {
  public barChartOptions = {
    responsive: true,
    scales: {
      x: { stacked: true },
      y: { stacked: true, beginAtZero: true }
    }
  };

  public barChartLabels = ['Release X'];
  public barChartData = [
    { label: 'Market 1', data: [20], backgroundColor: 'red' },
    { label: 'Market 2', data: [15], backgroundColor: 'orange' },
    { label: 'Market 3', data: [10], backgroundColor: 'yellow' },
    { label: 'Market 4', data: [5], backgroundColor: 'blue' }
   ];
   public barChartType = 'bar';
 }

Solution

  • You should use the below settings, reference Youtube Chart.js - How to Create an Overlapping Bar Chart in Chart js.

    public barChartOptions = {
      responsive: true,
      scales: {
        x: { stacked: true },
        y: { beginAtZero: true },
      },
    };
    

    Also notice that we need to sort the data based on bar thickness to get a nice layout with no ugly overlapping.

    ...
      public barChartData: ChartData<'bar'> = {
        labels: ['Markets'],
        datasets: [
          ...
        ].sort((a: any, b: any) => {
          return a.barThickness - b.barThickness;
        }), 
        ...
    

    Full Code:

    import { Component } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    import { BaseChartDirective } from 'ng2-charts';
    import { provideCharts, withDefaultRegisterables } from 'ng2-charts';
    import { ChartType, ChartData } from 'chart.js';
    
    @Component({
      selector: 'app-root',
      standalone: true,
      imports: [BaseChartDirective],
      template: `
        <div style="display: block;">
          <canvas
            baseChart
            [data]="barChartData"
            [labels]="barChartLabels"
            [options]="barChartOptions"
            [type]="barChartType"
            [legend]="true">
          </canvas>
        </div>
      `,
    })
    export class App {
      public barChartOptions = {
        responsive: true,
        scales: {
          x: { stacked: true },
          y: { beginAtZero: true },
        },
      };
    
      public barChartLabels: any = ['Release X'];
      public barChartData: ChartData<'bar'> = {
        labels: ['Markets'],
        datasets: [
          {
            data: [30],
            label: 'Market 1',
            barThickness: 30,
            backgroundColor: 'red',
          },
          {
            data: [40],
            label: 'Market 2',
            barThickness: 16,
            backgroundColor: 'orange',
          },
          {
            data: [10],
            label: 'Market 3',
            barThickness: 40,
            backgroundColor: 'yellow',
          },
          {
            data: [50],
            label: 'Market 4',
            barThickness: 70,
            backgroundColor: 'blue',
          },
        ].sort((a: any, b: any) => {
          return a.barThickness - b.barThickness;
        }),
      };
      public barChartType: ChartType = 'bar';
    }
    
    bootstrapApplication(App, {
      providers: [provideCharts(withDefaultRegisterables())],
    });
    

    Stackblitz Demo