[Chartjs]-Angular 9 Chart.js line chart with multiple line by date based

1👍

Notes

(1) To make my answer more didactic, I changed the name of this variables:

  • operators to uniqueOperators
  • x to uniqueOperator

(2) I changed some let to const, as it never reassigned

(3) Updates

  • handle multiple operators on same date
  • added complete code

Code

You need to updated your logic to something like that:

const uniqueOperators = [...new Set(data.map((x) => x.operatorName))];
const uniqueDates = [...new Set(data.map((x) => x.date))];

const subLabelDatasets = uniqueOperators.map((uniqueOperator) => {
  // find by operatorName and date in `data`
  // if not found, fill with `0`
  let datasets = uniqueDates.map((uniqueDate) =>
    data.find(
      (item) =>
        item.operatorName === uniqueOperator && item.date === uniqueDate
    )?.totalCount ?? 0
  );

  return {
    label: uniqueOperator,
    data: datasets,
  };
});

this will output an array like you expect:

[
    {label: 'OSEN+', data: [1, 7, 0, 1, 0, 0, 0]}
    {label: 'MBC', data: [0, 0, 1, 0, 1, 1, 15]}
]

This code will work even if the API outputed data contains multiple operators on same date like that:

const data = [
  { operatorName: 'OSEN+', date: '01-06-2023', totalCount: 1 },
  { operatorName: 'MBC', date: '01-06-2023', totalCount: 2 },
];

will ouput:

[
    {label: 'OSEN+', data: [1]}
    {label: 'MBC', data: [2]}
]

and you can use uniqueDates to replace the hard coded lineChartLabels this way

this.lineChartLabels = [...uniqueDates];

Complete code

(tested on your stackblitz demo)

export class AppComponent {
  /**Line chart */
  public lineChartType: ChartType = 'line';
  public lineChartData: any = [];
  public lineChartLabels: any = [];
  public lineChartOptions = {
    responsive: true,
    scales: {
      yAxes: [
        {
          ticks: {
            beginAtZero: true,
          },
        },
      ],
    },
  };
  /**Line chart */

  ngOnInit(): void {
    let data = [
      { operatorName: 'OSEN+', date: '05-04-2023', totalCount: 1 },
      { operatorName: 'OSEN+', date: '12-04-2023', totalCount: 7 },
      { operatorName: 'MBC', date: '01-06-2023', totalCount: 1 },
      { operatorName: 'OSEN+', date: '02-06-2023', totalCount: 1 },
      { operatorName: 'MBC', date: '09-06-2023', totalCount: 1 },
      { operatorName: 'MBC', date: '16-06-2023', totalCount: 1 },
      { operatorName: 'MBC', date: '23-06-2023', totalCount: 15 },
    ];

    const uniqueOperators = [...new Set(data.map((x) => x.operatorName))];
    const uniqueDates = [...new Set(data.map((x) => x.date))];

    this.lineChartData = uniqueOperators.map((uniqueOperator) => {
      // find by operatorName and date in `data`
      // if not found, fill with `0`
      let datasets = uniqueDates.map((uniqueDate) =>
        data.find(
          (item) =>
            item.operatorName === uniqueOperator && item.date === uniqueDate
        )?.totalCount ?? 0
      );
    
      return {
        label: uniqueOperator,
        data: datasets,
      };
    });

    this.lineChartLabels = [...uniqueDates];
  }
}

I hope it helps!

Leave a comment