Chartjs-How to line break a label object in ChartsJS (nested arrays won't work)

2đź‘Ť

âś…

There’s no option that can be defined to easily achieve what you’re looking for. An open feature request exists for such an option since 2016.

You’ll have to generate custom HTML legend using legendCallback.

Inspired by this answer, I came up with the following code that illustrates how this can be done in your case. It shouldn’t be too hard to further improve the styling of the legend labels and adapted them to your needs.

const chart = new Chart(document.getElementById("chart"), {
  type: "bar",
  data: {
    labels: [
      ['Utensilios para', 'escrita e artes'],
      ['Materiais não estruturado', 'de largo alcançe/recicláveis'],
      ['RepertĂłrio artĂ­stico-cultural e', 'cientĂ­fico de diferentes', 'origens Ă©tnico-raciais']
    ],
    datasets: [{
        label: "Não há material presente",
        data: [5, 8, 4],
        fill: false,
        backgroundColor: "rgba(255, 99, 132, 0.2)",
        borderColor: "rgb(255, 99, 132)",
        borderWidth: 1
      },
      {
        label: ["Material presente", "mas crianças não usaram"],
        data: [3, 5, 4],
        fill: false,
        backgroundColor: "rgba(255, 159, 64, 0.2)",
        borderColor: "rgb(255, 159, 64)",
        borderWidth: 1
      },
      {
        label: "Crianças usaram os materiais",
        data: [6, 5, 7],
        fill: false,
        backgroundColor: "rgba(255, 205, 86, 0.2)",
        borderColor: "rgb(255, 205, 86)",
        borderWidth: 1
      }
    ]
  },
  options: {
    legend: {
      display: false
    },
    tooltips: {
      callbacks: {        
        title: (tooltipItems, data) => data.labels[tooltipItems[0].index],
        label: (tooltipItems, data) =>
          data.datasets[tooltipItems.datasetIndex].label + ': ' + tooltipItems.value + '%'
      }
    },
    legendCallback: chart => {
      let html = '<ul class="' + chart.id + '-legend">';
      chart.data.datasets.forEach((ds, i) => {
        html += '<li><span id="legend-' + i + '-item" style="background-color:' + ds.backgroundColor + '" onclick="updateDataset(event, \'' + i + '\')">';
        html += Array.isArray(ds.label) ? ds.label.join('<br />') : ds.label;
        html += '</span></li>';
      });
      return html + '</ul>';
    },
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true
        }
      }]
    }
  }
});

$("#legend").html(chart.generateLegend());

// Show/hide chart by click legend
updateDataset = (e, dsIndex) => {
  let hide = !chart.data.datasets[dsIndex].hidden;
  chart.data.datasets[dsIndex].hidden = hide;
  if (hide) {
    $('#' + e.path[0].id).css("text-decoration", "line-through");
  } else {
    $('#' + e.path[0].id).css("text-decoration", "");
  }
  chart.update();
};
#legend>ul {
  padding: 0;
  text-align: center;
}

#legend li {
  cursor: pointer;
  margin: 10px 10px;
  display: inline-table;
}

#legend li span {
  position: relative;
  padding: 3px 5px;
  z-index: 2;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 12px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<div>
  <div id="legend"></div>
  <canvas id="chart"></canvas>
</div>

UPDATE

Meanwhile I answered a similar question and invested some time to properly define the styling of the legend labels. Please have a look at this anwser.

Leave a comment