Home > OS >  How can I implement a custom dataset data structure for a Line Chart.js?
How can I implement a custom dataset data structure for a Line Chart.js?

Time:10-28

How can I implement the custom property data structure for a dataset as mentioned below without hacking the index.esm.d.ts file?

I want to implement a custom dataset data structure similar to here in a line chart. I am doing this in Angular and using ng2-charts.

Pertinent library versions:

"@angular/core": "^14.2.0"
"@types/chart.js": "^2.9.37"
"chart.js": "^3.9.1"
"ng2-charts": "^4.0.1"
"typescript": "~4.7.2"
"tslib": "^2.3.0",

Here is a simplified version of the dataset data structure I want to implement:

data: [
  {id: '1', nested: {value: 500, extra: 'one'}},
  {id: '2', nested: {value: 1500, extra: 'two'}},
],

Unfortunately, I get the following typescript error when implementing this: error TS2322: Type '{ id: string; nested: { value: number; extra: string; }; }' is not assignable to type 'number | ScatterDataPoint | BubbleDataPoint | null'.

If I modify the index.esm.d.ts file with a CustomDataPoint:

export interface CustomDataPoint {
  id: string,
  nested: {
    value: number,
    extra: string
  }
}

export interface ChartTypeRegistry {
...

line: {
  chartOptions: LineControllerChartOptions;
  datasetOptions: LineControllerDatasetOptions & FillerControllerDatasetOptions;
  defaultDataPoint: CustomDataPoint | ScatterDataPoint | number | null; //### modified
  // defaultDataPoint: ScatterDataPoint | number | null; //### original
  metaExtensions: {};
  parsedDataType: CartesianParsedData;
  scales: keyof CartesianScaleTypeRegistry;
};

...
}

I no longer get the typescript error. Yay! (;P)

How can I implement the custom property data structure for a dataset as mentioned above without hacking the index.esm.d.ts file?

Here is a minimal code set to reproduce this...

line-chart.component.ts:

import { Component, OnInit } from '@angular/core';
import {ChartConfiguration, ChartType} from "chart.js";

@Component({
  selector: 'app-chart-one',
  templateUrl: './chart-one.component.html',
  styleUrls: ['./chart-one.component.css']
})
export class ChartOneComponent implements OnInit {

  public chartData: ChartConfiguration['data'] = {
    datasets: []
  };

  public chartOptions: ChartConfiguration['options'];

  public chartType: ChartType = 'line';

  constructor() {}

  ngOnInit(): void {
    this.chartData.datasets = [
      {
        data: [
          {id: '1', nested: {value: 500, extra: 'one'}}, //TS Error here
          {id: '2', nested: {value: 1500, extra: 'two'}}, //TS Error here
        ],
        label: 'set 1',
        borderColor: '#3cba9f',
        fill: false,
      }
    ]

    this.chartOptions = {
      responsive: true,
      parsing: {
        xAxisKey: 'id',
        yAxisKey: 'nested.value'
      },
    };
  }
}

line-chart.component.html:

<div style="display: block">
  <canvas baseChart
          [data]="chartData"
          [options]="chartOptions"
          [type]="chartType">
  </canvas>
</div>

CodePudding user response:

As described in the docs here you can pass your own custom datatype:

import {ChartData} from 'chart.js';

const datasets: ChartData<'bar', {key: string, value: number} []> = {
  datasets: [{
    data: [{key: 'Sales', value: 20}, {key: 'Revenue', value: 10}],
    parsing: {
      xAxisKey: 'key',
      yAxisKey: 'value'
    }
  }],
};
  • Related