0

I have two data sets that I want to format into two column charts.

(2) [{…}, {…}]
    0:
    historyDate: "2021-02-10T10:00:000Z"
    documentStatusHistory:
        CANCELLED: 6
        COMPLETED: 52
        IN_PROGRESS: 1
        OPEN: 1
        PHASE_OUT: 1
    1:
    historyDate: "2021-02-17T10:00:000Z"
    documentStatusHistory:
        CANCELLED: 6
        COMPLETED: 52
        IN_PROGRESS: 1
        OPEN: 1
        PHASE_OUT: 1

The chart is configured in ngAfterContentInit

ngAfterContentInit() {
    const chartOptions: Options = this.createDefaultColumnOptions();
    chartOptions.title.text = this.chartTitle;
    this.resultChart = Highcharts.chart(this.resultChartTarget.nativeElement, chartOptions);
    this.resultChart.addSeries(this.buildColumnSeries(this.uuidService.getNewUuid(), this.chartData));
  }

The column data are created here

private buildColumnSeries(id: string, chartData: any[]) {
    const options: SeriesOptions = {
      id,
      type: 'column',
      data: [],
    } as SeriesOptions;

    chartData.forEach((item) => {
      const date = new Date(item.historyDate);
      const newDate = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate());

      for (const status in item.documentStatusHistory) {
        this.resultChart.addSeries({
                                     type: 'column',
                                     yAxis: 0,
                                     name: status.replace('_', ' '),
                                     data: [[newDate, item.documentStatusHistory[status]]],
                                     color: DisplayUtil.getStatusColor(status)
                                   });
      }
    });
    return options;
  }

and here the chart options

private createDefaultColumnOptions(): Options {
    return {
      chart: {
        zoomType: 'xy',
        marginLeft: 70,
        marginRight: 70
      },
      title: {
        useHTML: true
      },
      legend: {
        verticalAlign: 'top',
        labelFormat: '<b>{name}</b>',
        enabled: true
      },
      xAxis: {
        type: 'datetime',
        dateTimeLabelFormats: {
          week: '%e. %b'
        },
        title: {
          text: 'Date'
        }
      },
      yAxis: [
        { // Primary yAxis
          title: {
            text: 'Total ' + this.chartTitle
          }
        }
      ],
      tooltip: {
        shared: true
      },
      plotOptions: {
        column: {
          stacking: 'normal'
        },
        series: {
          cursor: 'pointer'
        }
      },
      credits: {
        enabled: false
      }
    } as Options;
  }
}

At the end I get the following chart

enter image description here

I am now not entirely clear why I am getting the legend twice. the columns are each correctly structured. Does anyone have any indication of what's wrong here?

4

1 回答 1

0

The current solution is as follows.

private buildColumnSeries(id: string, chartData: any[]) {

    const options: SeriesOptions = {
      id,
      type: 'column',
      data: [],
    } as SeriesOptions;

    console.log(chartData);

    const OPEN = [];
    const COMPLETED = [];
    const IN_PROGRESS = [];
    const PHASE_OUT = [];
    const CANCELLED = [];

    chartData.forEach((item) => {    
      OPEN.push(item.documentStatusHistory.OPEN);
      COMPLETED.push(item.documentStatusHistory.COMPLETED);
      IN_PROGRESS.push(item.documentStatusHistory.IN_PROGRESS);
      PHASE_OUT.push(item.documentStatusHistory.PHASE_OUT);
      CANCELLED.push(item.documentStatusHistory.CANCELLED);
    });

    this.resultChart.addSeries({
                                 type: 'column',
                                 yAxis: 0,
                                 name: 'OPEN',
                                 data: OPEN,
                                 color: DisplayUtil.getStatusColor('OPEN')
                               });

    this.resultChart.addSeries({
                                 type: 'column',
                                 yAxis: 0,
                                 name: 'COMPLETED',
                                 data: COMPLETED,
                                 color: DisplayUtil.getStatusColor('COMPLETED')
                               });

    this.resultChart.addSeries({
                                 type: 'column',
                                 yAxis: 0,
                                 name: 'IN_PROGRESS',
                                 data: IN_PROGRESS,
                                 color: DisplayUtil.getStatusColor('IN_PROGRESS')
                               });

    this.resultChart.addSeries({
                                 type: 'column',
                                 yAxis: 0,
                                 name: 'PHASE_OUT',
                                 data: PHASE_OUT,
                                 color: DisplayUtil.getStatusColor('PHASE_OUT')
                               });

    this.resultChart.addSeries({
                                 type: 'column',
                                 yAxis: 0,
                                 name: 'CANCELLED',
                                 data: CANCELLED,
                                 color: DisplayUtil.getStatusColor('CANCELLED')
                               });

    return options;
  }

But I don't want to keep the status hard-coded but dynamic, because I don't know whether the status names can change.

so after a while, here the solution for dynamic kays.

private buildColumnSeries(id: string, chartData: any[]) {

    const options: SeriesOptions = {
      id,
      type: 'column',
      data: [],
    } as SeriesOptions;

    const data = [];

    const map = new Map();

    chartData.forEach((item) => {

      const keys = Object.keys(item.documentStatusHistory);
      keys.forEach((key) => {

        let found = false;
        data.find(element => {
          if (element.key === key) {
            found = true;
          }
        });

        if (found) {
          const array = map.get(key);
          array.push(item.documentStatusHistory[key]);
          map.set(key, array);
        } else {
          data.push({key, series: [1]});
          map.set(key, [item.documentStatusHistory[key]]);
        }

      });
    });

    map.forEach((value: [], key: string) => {
      this.resultChart.addSeries({
                                   type: 'column',
                                   yAxis: 0,
                                   name: key,
                                   data: value,
                                   color: DisplayUtil.getStatusColor(key)
                                 });
    });
    return options;
  }
于 2021-02-18T10:55:54.750 回答