Hafnernuss
Hafnernuss

Reputation: 2817

Chart.js Custom parsing with floating bar chart

I have a floating bar chart that somewhat represents a Gantt chart:

enter image description here

The dataset looks as follows:

{
    "labels": [
        "Uwe Austermühle",
        "Helmar Conradi",
        "Gero Dippel"
    ],
    "datasets": [
        {
            "data": [
                [
                    "2023-01-05T17:00:00.000Z",
                    "2023-01-08T17:00:00.000Z"
                ],
                [
                    "2022-12-01T12:34:00.000Z",
                    "2023-02-28T12:34:00.000Z"
                ],
                [
                    "2023-01-24T12:39:16.202Z",
                    "2023-02-23T12:39:00.000Z"
                ]
            ],
            "barPercentage": 0.5,
            "backgroundColor": "rgba(255, 193, 7, 0.8)"
        }
    ]
}

Here is a simplified fiddle.

Problems arise when I try to extend my dataset model by an additional property. Let's say, I want to store some string for each "bar", so that the current model [Date, Date] becomes something like this:

{
  range: [Date, Date],
  text: string,
}

Which would mean, my Dataset would look like that:

{
    "labels": [
        "Uwe Austermühle",
        "Helmar Conradi",
        "Gero Dippel"
    ],
    "datasets": [
        {
            "data": [
                {
                    "range": [
                        "2023-01-05T17:00:00.000Z",
                        "2023-01-08T17:00:00.000Z"
                    ],
                    "annotation": "someText"
                },
                {
                    "range": [
                        "2022-12-01T12:34:00.000Z",
                        "2023-02-28T12:34:00.000Z"
                    ],
                    "annotation": "someText"
                },
                {
                    "range": [
                        "2023-01-24T12:39:16.202Z",
                        "2023-02-23T12:39:00.000Z"
                    ],
                    "annotation": "someText"
                }
            ],
            "barPercentage": 0.5,
            "backgroundColor": "rgba(255, 193, 7, 0.8)",
            "parsing": {
                "yAxisKey": "range"
            }
        }
    ]
}

However, this gives me a completly empty chart, as you can see here. What am I doing wrong?

Upvotes: 2

Views: 823

Answers (2)

kikon
kikon

Reputation: 8620

@user2057925's answer is perfectly right, as well as @Hafnernuss comment, and unless there's a deep reason behind this (which I fail to imagine - please let me know) it qualifies as a bug: labels in bar chart are ignored if data is specified through an object.

I certainly don't recommend the following as a feasible solution to the case in question, but since it may be helpful in the future to address this issue, I'd mention that it can be solved (patched) in the source code, if BarController#parseObjectData does the same as the BarController#parseArrayAndPrimitive - here, that is, add an || iScale.parse(labels[i], i) so it uses the labels if the yAxisKey (or xAxisKey) way fails. So the patched BarController#parseObjectData could look like:

    parseObjectData(meta, data, start, count) {
        const {iScale, vScale} = meta;
        const {xAxisKey = 'x', yAxisKey = 'y'} = this._parsing;
        const iAxisKey = iScale.axis === 'x' ? xAxisKey : yAxisKey;
        const vAxisKey = vScale.axis === 'x' ? xAxisKey : yAxisKey;
        const parsed = [];
        const labels = iScale.getLabels();
        let i, ilen, item, obj;
        for (i = start, ilen = start + count; i < ilen; ++i) {
            obj = data[i];
            item = {};
            item[iScale.axis] = iScale.parse(resolveObjectKey(obj, iAxisKey) || labels[i], i);
            parsed.push(parseValue(resolveObjectKey(obj, vAxisKey), item, vScale, i));
        }
        return parsed;
   }

Again, not as practical solution, but as a proof of concept, here's a replit with it working as @Hafnernuss rightfully expected it to.

Upvotes: 1

user2057925
user2057925

Reputation: 2653

I think you could change "yAxisKey" to "xAxisKey" because it's horizontal bar (indexAxis: "y").

Furthermore you could add the "y" value to your data with the label instead to use labels (see chartjs doc: https://www.chartjs.org/docs/latest/general/data-structures.html#parsing).

Dataset:

      datasets: [
          {
              data: [
                  {
                      y: "Uwe Austermühle",
                      range: [1,2],
                      annotation: 'test'
                  },
                  {
                      y: "Helmar Conradi",
                      range: [5,6],
                      annotation: 'test'
                  },
                  {
                      y: "Gero Dippel",
                      range: [7,8],
                      annotation: 'test'
                  },
              ],
              barPercentage: 0.5,
              backgroundColor: "rgba(255, 193, 7, 0.8)",
              parsing: {
                xAxisKey: 'range'
              }
          }
      ]
  },
  options: {
    indexAxis: 'y',

Upvotes: 3

Related Questions