[Chartjs]-Chart JS tooltip appears differently when set from script instead of html

1👍

The reason the formatting is different is because chart.js does not support the options postfix and hasIndicator, seems like your wrapper is styling the tooltip and taking those extra options and transforms the tooltip itself. If you want to make your chart via script you need to follow the normal documentation.

About the tooltip getting cut off guess its somewhere else that it might go wrong because standard behaviour it adjusts the tooltip placement so that it is in the chart area:

const options = {
   type: 'line',
   data: {
     labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
     datasets: [
       {
        label: '# of Votes',
        data: [12, 19, 2, 5, 2, 3],
        borderWidth: 1
       },   
       {
        label: '# of Points',
        data: [7, 11, 5, 8, 3, 7],
        borderWidth: 1
       }
     ]
   },
   options: {
   }
};

const ctx =  document.getElementById('chartJSContainer').getContext('2d');

new Chart(ctx, options);
canvas { 
   background-color : #eee;
}
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.4"></script>

<canvas id="chartJSContainer" width="600" height="400"></canvas>

0👍

Your code in your question is for ….. chart.js v2.xx

v3.xx is not backwards compatible with v2.xx
v3.xx has better performance, hence you might consider migrating

Anyhow, I offer you 2 solutions for both versions:

  1. code for chart.js v2.9.4 (latest for v2.x)
  2. code for chart.js v3.5.1 (latest for v3.x)
    I migrated your code to v3.x

I used some sample data (as I cannot fetch your data from here).

v2.x

Replacing postfix: '%' with following callback function:

options: {
  ...
      tooltips: {
        usePointStyle: true,
        // postfix: '%',
        callbacks: {  // <-- to replace 'postfix:'
          label: function(context) {
            return context.yLabel + '%' || '';
          }
        }
  ...
}

See following complete code for v2.x and Run code snippet to see result:

const popCanvasName = document.getElementById('occChart').getContext('2d');

let myData = [];
let myLabels = [];
const myOccupancy = { // <-- let's use sample data meanwhile
  "LabelList" : ["2021-08-02","2021-08-03","2021-08-04","2021-08-05","2021-08-06"],
  "DataList" : [39,41,42,30,21]
};

function showChart() {
  myData = myOccupancy.DataList;
  myLabels = myOccupancy.LabelList;
  // console.log(myData);
  // console.log(myLabels);

  const barChartName = new Chart(popCanvasName, {
    type: 'line',
    data: {
      labels: myLabels,
      datasets: [{
        data: myData,
        backgroundColor: ['rgba(55, 125, 255, 0.5)', 'rgba(255, 255, 255, 0.5)'],
        fill: true, // <-- to show backgroundColor
        borderColor: '#377dff',
        borderWidth: 2,
        pointRadius: 0,
        pointHoverRadius: 0
      }]
    },
    options: {
      aspectRatio: 5,
      responsive: true,
      interaction: {
        intersect: false,
        mode: 'nearest'
      },
      scales: {
        yAxes: [{
          display: false
        }],
        xAxes: [{
          type: 'time', // load moment.js and adapter for this to work
          display: true,
          time: {
            unit: 'week',
            displayFormats: {
              hour: 'h:mm a',
              day: 'ddd',
              week: 'dddd',
              month: 'MMM'
            },
            tooltipFormat: 'dddd, MMM DD, YYYY' // modify format string to your needs
          }
        }]
      },
      tooltips: {
        usePointStyle: true,
        // postfix: '%',
        callbacks: {  // you can use this callback
          label: function(context) {
            return context.yLabel + '%' || '';
          }
        },
        // hasIndicator: true,
        intersect: false
      },
      legend: {
        display: false
      }
    }
  });
};

function getChartData() {
  return fetch('./Index?handler=OccupancyChartData', {
    method: 'get',
    headers: {
      'Content-Type': 'application/json;charset=UTF-8'
    }
  })
  .then(function(response) {
    console.log(response);
    if (response.ok) {
      return response.text();
    } else {
      throw Error('Response Not OK');
    }
})
.then(function(text) {
    try {
return JSON.parse(text);
    } catch (err) {
throw Error('Method Not Found');
    }
})
.then(function(responseJSON) {
    myOccupancy = responseJSON;
    showChart();
});
};

showChart();

/* We use sample data meanwhile
$(document).on('ready', function() {

  // getChartData();  <-- we use sample data meanwhile

  // initialization of circles


  $('.js-circle').each(function() {
    var circle = $.HSCore.components.HSCircles.init($(this));
  });

  $('.js-chart').each(function () {
    var chart = $.HSCore.components.HSChartJS.init($(this));
  });

});
*/
<!-- get latest version of Chart.js v2.x -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.4"></script>

<!-- You need moment.js and adapter for time to work at x-Axis -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment"></script>

<canvas id="occChart" width="320"></canvas>

v3.x

Replacing postfix: '%' with following callback function:

options: {
  ...
    plugins: { // toolip within plugin now
      tooltip: { // before tooltips  --> now toolip (singular)
        usePointStyle: true,
        // postfix: '%',
        callbacks: {  // <-- replacing 'postfix:'
            label: function(context) {
              return context.parsed.y + '%' || '';
            }
        }
    }
  ...
}

See following complete code for v3.x and Run code snippet to see result:

const popCanvasName = document.getElementById('occChart').getContext('2d');

let myData = [];
let myLabels = [];
const myOccupancy = { // <-- let's use sample data meanwhile
  "LabelList" : ["2021-08-02","2021-08-03","2021-08-04","2021-08-05","2021-08-06"],
  "DataList" : [39,41,42,30,21]
};

function showChart() {
  myData = myOccupancy.DataList;
  myLabels = myOccupancy.LabelList;
  // console.log(myData);
  // console.log(myLabels);

  const barChartName = new Chart(popCanvasName, {
    type: 'line',
    data: {
      labels: myLabels,
      datasets: [{
        data: myData,
        backgroundColor: ['rgba(55, 125, 255, 0.5)', 'rgba(255, 255, 255, 0.5)'],
        fill: true, // <-- to show backgroundColor
        borderColor: '#377dff',
        borderWidth: 2,
        pointRadius: 0,
        pointHoverRadius: 0
      }]
    },
    options: {
      aspectRatio: 5,
      responsive: true,
      interaction: { // before hover  --> now 'interaction'
        intersect: false,
        mode: 'nearest'
      },
      scales: {
        yAxes: { // before '[{'   now '{' (not an array anymore)
          display: false
        },
        xAxes: { // before '[{'  --> now '{' (not an array anymore)
          type: 'time', // load moment.js and adapter for this to work
          display: false,
          time: {
            unit: 'week',
            displayFormats: {
              hour: 'h:mm a',
              day: 'ddd',
              week: 'dddd',
              month: 'MMM'
            },
            tooltipFormat: 'dddd, MMM DD, YYYY' // modify format string to your needs
          }
        }
      },
      plugins: {
        tooltip: { // before tooltips  --> now toolip (singular) within plugin
          usePointStyle: true,
          // postfix: '%',
          callbacks: {  // <-- replacing 'postfix:'
            label: function(context) {
              return context.parsed.y + '%' || '';
            }
          },
          hasIndicator: true,
          intersect: false
        },
        legend: { // --> now within plugin
          display: false
        }
      }
    }
  });
};

function getChartData() {
  return fetch('./Index?handler=OccupancyChartData', {
    method: 'get',
    headers: {
      'Content-Type': 'application/json;charset=UTF-8'
    }
  })
  .then(function(response) {
    console.log(response);
    if (response.ok) {
      return response.text();
    } else {
      throw Error('Response Not OK');
    }
})
.then(function(text) {
    try {
return JSON.parse(text);
    } catch (err) {
throw Error('Method Not Found');
    }
})
.then(function(responseJSON) {
    myOccupancy = responseJSON;
    showChart();
});
};

showChart();

/* We use sample data meanwhile
$(document).on('ready', function() {

  // getChartData();  <-- we use sample data meanwhile

  // initialization of circles


  $('.js-circle').each(function() {
    var circle = $.HSCore.components.HSCircles.init($(this));
  });

  $('.js-chart').each(function () {
    var chart = $.HSCore.components.HSChartJS.init($(this));
  });

});
*/
<!-- get latest version of Chart.js, now at v3.5.1 -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

<!-- You need moment.js and adapter for time to work at x-Axis -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment"></script>

<canvas id="occChart" width="320"></canvas>

Leave a comment