2

I'm working with chart.js and need to make a legend on horizontalBar, but isn't working because my data have 5 values and on legend label is showing only one and the value is "undefined", this undefined value control all chart colors.

Here is my code:

horizontalMeters = new Chart("chartHorizontalBar", {
    type: "bar",
    data: {
      labels: ["red", "blue", "green"],
      datasets: [{
        backgroundColor: ["red", "blue", "green"],
        data: [123, 321, 213]
      }]
    },
    options: {
      indexAxis: 'y',
      plugins: {
        legend: {
          display: true,
          position: "right",
        }       
      },
    }
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.js"
    integrity="sha512-TW5s0IT/IppJtu76UbysrBH9Hy/5X41OTAbQuffZFU6lQ1rdcLHzpU5BzVvr/YFykoiMYZVWlr/PX1mDcfM9Qg=="
    crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script
    src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.0.0-rc.1/chartjs-plugin-datalabels.min.js"
    integrity="sha512-+UYTD5L/bU1sgAfWA0ELK5RlQ811q8wZIocqI7+K0Lhh8yVdIoAMEs96wJAIbgFvzynPm36ZCXtkydxu1cs27w=="
    crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    
    
<canvas id="chartHorizontalBar"></canvas>

I'm using chart.js v3.7 and a datalabels plugin v2.0, i don't know if this plugin and version have a conflict, but i make a Doughnot Chart with the same CDN's and that one works

The code:

doughnotQualities = new Chart("chartDoughnutBar", {
    type: "doughnut",
    data: {
      labels: ["red", "blue", "green"],
      datasets: [{
        backgroundColor: ["red", "blue", "green"],
        data: [123, 321, 213]
      }]
    },
    options: {
      plugins: {
        legend: { 
          display: true, 
          position: "right"
        },
      },
    }
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.js"
    integrity="sha512-TW5s0IT/IppJtu76UbysrBH9Hy/5X41OTAbQuffZFU6lQ1rdcLHzpU5BzVvr/YFykoiMYZVWlr/PX1mDcfM9Qg=="
    crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <script
    src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.0.0-rc.1/chartjs-plugin-datalabels.min.js"
    integrity="sha512-+UYTD5L/bU1sgAfWA0ELK5RlQ811q8wZIocqI7+K0Lhh8yVdIoAMEs96wJAIbgFvzynPm36ZCXtkydxu1cs27w=="
    crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    
<canvas id="chartDoughnutBar"></canvas>

That's the difference between charts: enter image description here

enter image description here

Does anyone know how to solve this?

Leonardi
  • 43
  • 1
  • 6

3 Answers3

3

It shows undefined since it takes the label of the dataset, for doughnut and pie charts chart.js overrides the legend generator to use the labels array instead.

You can use multiple datasets with null values and then set the skipNull options to true like so:

Chart.register(ChartDataLabels)

horizontalMeters = new Chart("chartHorizontalBar", {
  type: "bar",
  data: {
    labels: ["red", "blue", "green"],
    datasets: [{
      backgroundColor: "red",
      label: "red",
      data: [123, null, null]
    }, {
      backgroundColor: "blue",
      label: "blue",
      data: [null, 321, null]
    }, {
      backgroundColor: "green",
      label: "green",
      data: [null, null, 213]
    }]
  },
  options: {
    indexAxis: 'y',
    skipNull: true,
    plugins: {
      legend: {
        display: true,
        position: "right",
      }
    },
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.js" integrity="sha512-TW5s0IT/IppJtu76UbysrBH9Hy/5X41OTAbQuffZFU6lQ1rdcLHzpU5BzVvr/YFykoiMYZVWlr/PX1mDcfM9Qg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.0.0-rc.1/chartjs-plugin-datalabels.min.js" integrity="sha512-+UYTD5L/bU1sgAfWA0ELK5RlQ811q8wZIocqI7+K0Lhh8yVdIoAMEs96wJAIbgFvzynPm36ZCXtkydxu1cs27w==" crossorigin="anonymous"
  referrerpolicy="no-referrer"></script>


<canvas id="chartHorizontalBar"></canvas>

Edit:
To use the datalabels plugin you will need to register it either inline or globally as in my example.

LeeLenalee
  • 27,463
  • 6
  • 45
  • 69
  • That's a good way, but how i do that work if data came from a variable? on the `data: [123, 321, 213]` i need something like `data: variableWithDatas` – Leonardi Dec 28 '21 at 16:08
  • 1
    You will need to transform it into a structure like this first, by looping through it and making datasets, make data arrays with all null values and only put the value in the index of that dataset – LeeLenalee Dec 28 '21 at 16:10
  • is normal doughnot one works and bar don't or is a bug? – Leonardi Dec 28 '21 at 16:15
  • It is normal, as stated in my answer chart.js overrides the legend generate function so it uses the labels array and not the indevidual label fields in the datasets since you interact in a different way with a doughnut chart as with a bar chart. So the bar works just fine, you are just using it wrong/expecting wrong outcome – LeeLenalee Dec 28 '21 at 16:19
0

This answer explains how to solve the problem with a vertical bar chart.

The code needs to be slightly adapted to also work for a horizontal bar chart.

Please take a look at the following code and see how it could be done in your case.

new Chart('myChart', {
  type: 'bar',
  plugins: [{
    afterInit: chart => {
      let dataset = chart.data.datasets[0];
      chart.data.datasets = chart.data.labels.map((l, i) => ({
        label: l,
        data: [{ x: dataset.data[i], y: i }],
        backgroundColor: dataset.backgroundColor[i],
        categoryPercentage: 1
      }));
      chart.data.labels = undefined;
    },
    beforeLayout: chart => {
      chart.options.scales.y1.labels = chart.data.datasets.filter((ds, i) => !chart.getDatasetMeta(i).hidden).map(ds => ds.label);
    }
  }],
  data: {
    labels: ['Red', 'Blue', 'Green'],
    datasets: [{
      data: [123, 321, 213],
      backgroundColor: ['red', 'blue', 'green']
    }]
  },
  options: {
    indexAxis: 'y',
    maintainAspectRatio: false,
    plugins: {
      legend: {
        position: 'right'
      },
      tooltip: {
        callbacks: {
          title: () => null
        }
      }
    },
    scales: {
      y: {
        display: false
      },
      y1: {
        offset: true
      }
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.js"></script>
<canvas id="myChart"></canvas>
uminder
  • 23,831
  • 5
  • 37
  • 72
0

In your dataset object, just add label:''. This will remove the undefined interpulated string.