4

I have a line graph created with charts.js and I would like to display data labels only for the last values of the x axis. Meaning I want to show all the data points but showing the data label only for the last data point.

For example:

enter image description here

I was able to show data labels for every points of all the data sets using this answer: Show values on top of bars in chart.js but my aim is to display only 1 label for the last data point, and I am a bit lost here.

Here is codepen link

var TITLE = 'Trend Coronavirus per Giorno';

var X_AXIS = '';  // x-axis label and label in tooltip
var Y_AXIS = ''; // y-axis label and label in tooltip

var BEGIN_AT_ZERO = false;  // Should x-axis start from 0? `true` or `false`

var SHOW_GRID = true; // `true` to show the grid, `false` to hide
var SHOW_LEGEND = true; // `true` to show the legend, `false` to hide


$(document).ready(function() {

  // Read data file and create a chart
  $.get('https://localchef.it/csv/trendbyday.csv', function(csvString) {

    var data = Papa.parse(csvString).data;
    var timeLabels = data.slice(1).map(function(row) { return row[0]; });

    var datasets = [];
    for (var i = 1; i < data[0].length; i++) {
      datasets.push(
        {
          label: data[0][i], // column name
          data: data.slice(1).map(function(row) {return row[i]}), // data in that column
          fill: false // `true` for area charts, `false` for regular line charts
        }
      )
    }

    // Get container for the chart
    var ctx = document.getElementById('chart-container').getContext('2d');

    new Chart(ctx, {
      type: 'line',

      data: {
        labels: timeLabels,
        datasets: datasets,
      },

      options: {
        "animation": {
            "duration": 1,
                        "onComplete": function () {
                            var chartInstance = this.chart,
                                ctx = chartInstance.ctx;
                            
                            ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
                            ctx.textAlign = 'center';
                            ctx.textBaseline = 'bottom';

                            this.data.datasets.forEach(function (dataset, i) {
                                var meta = chartInstance.controller.getDatasetMeta(i);
                                meta.data.forEach(function (line) {
                                    var data = dataset.data[1];                            
                                    ctx.fillText(data, line._model.x, line._model.y - 5);
                                });
                            });
                        }
        },
        title: {
          display: true,
          text: TITLE,
          fontSize: 16,
        },

        legend: {
          display: true,
          labels: {
            boxWidth: 15,
          },
        },
        maintainAspectRatio: false,
        scales: {
          xAxes: [{
            scaleLabel: {
              display: X_AXIS !== '',
              labelString: X_AXIS
            },
            gridLines: {
              display: false,
            },
            ticks: {
              callback: function(value, index, values) {
                return value.toLocaleString();
              }
            }
          }],
          yAxes: [{
            beginAtZero: true,
            scaleLabel: {
              display: Y_AXIS !== '',
              labelString: Y_AXIS
            },
            gridLines: {
              display: SHOW_GRID,
            },
            ticks: {
              beginAtZero: BEGIN_AT_ZERO,
              callback: function(value, index, values) {
                return value.toLocaleString()
              }
            }
          }]
        },
        tooltips: {
          displayColors: true,
          mode: 'index',
          intersect: false,
          callbacks: {
            label: function(tooltipItem, all) {
              return all.datasets[tooltipItem.datasetIndex].label
                + ': ' + tooltipItem.yLabel.toLocaleString();
}
          }
        },
        plugins: {
          colorschemes: {
            scheme: 'brewer.Paired12'
          }
        }
      }
    });

  });

});
<!-- Load jQuery -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  
<!-- Load Chart.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js"></script>
<script src="https://localchef.it/csv/jscolors.js"></script>

<!-- Load PapaParse to read csv files -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.1.0/papaparse.min.js"></script>
<div>
  <canvas id="chart-container" style="height: 400px; width: 100%"></canvas>
</div>
<script src="script.js"></script>

Can anybody help me out?

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
TMaLuST
  • 41
  • 1
  • 3

3 Answers3

3

This can be done with the DataLabels Plugin.

Add the JS file to your HTML:

<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@0.7.0"></script>

Note: be sure to add it below the Chart.js script include.

Enable the datalabels plugin and add a custom labels formatter to the options configuration object:

plugins: {
    datalabels: {
        formatter: function(value, context) {
            if (context.dataIndex === context.dataset.data.length - 1)
            {
                return value.y;
            }
            return "";
        }
    },
}
sboulema
  • 837
  • 1
  • 10
  • 22
  • 2
    This one got me in the right direction, however, it only hides the text and wont work if there is more shown, like a background colour. Using the `display` callback is the better choice: `display: function (context){ return (context.dataIndex === context.dataset.data.length - 1); }` – Chuck Feb 10 '21 at 09:07
0

Using DataLabels Plugin, as pointed out by @chuck in one of the comments. display is the way to go.

plugins: {
    datalabels: {
        display: function(value, context) {
            return context.dataIndex === context.dataset.data.length - 1;
        }
    },
}
Ali
  • 166
  • 1
  • 8
-1

To show only that last points, you could just unset the unneeded data (json array).

To do so, (dont know what kind of data source you got) loop throught the array and use

unset($my_var["key_of_value_to_delete"]);

Normal array:

delete array[0];

Best thing to do would be: Only retrieve the data you really need. Send your Server-Request in the way, you only get the results you really need. Keywords:

Queries and filtering

xKean
  • 94
  • 6
  • Thanks for the reply! Unfortunately this is not what I need. I need to retrive and show all the data points, what I am trying to achieve is to display the data point label only for the last data point. Hope it is clearer now :) – TMaLuST Sep 02 '20 at 09:50