I am trying to customize a Chart JS element from a template (Front Dashboard)
In the template the example is set up from the HTML as follows
<canvas class="js-chart"
data-hs-chartjs-options='{
"type": "line",
"data": {
"labels": ["1 May","2 May","3 May","4 May","5 May","6 May","7 May","8 May","9 May","10 May","11 May","12 May","13 May","14 May","15 May","16 May","17 May","18 May","19 May","20 May","21 May","22 May","23 May","24 May","25 May","26 May","27 May","28 May","29 May","30 May","31 May"],
"datasets": [{
"data": [25,18,30,31,35,35,60,60,60,75,21,20,24,20,18,17,15,17,30,120,120,120,100,90,75,90,90,90,75,70,60],
"backgroundColor": ["rgba(55, 125, 255, 0)", "rgba(255, 255, 255, 0)"],
"borderColor": "#377dff",
"borderWidth": 2,
"pointRadius": 0,
"pointHoverRadius": 0
}]
},
"options": {
"scales": {
"yAxes": [{
"display": false
}],
"xAxes": [{
"display": false
}]
},
"hover": {
"mode": "nearest",
"intersect": false
},
"tooltips": {
"postfix": "%",
"hasIndicator": true,
"intersect": false
}
}
}'>
</canvas>
This displays a nicely formatted Tooltip
but when I setup the chart from script with the same structure/config, the tooltip formatting changes and it also is clipped inside the bounds of the chart.
var myData = [];
var myLabels = [];
var myOccupancy;
function showChart() {
myData = myOccupancy.DataList;
myLabels = myOccupancy.LabelList;
console.log(myData);
console.log(myLabels);
let popCanvasName = document.getElementById("occChart");
let barChartName = new Chart(popCanvasName, {
type: 'line',
data: {
labels: myLabels,
datasets: [
{
data: myData,
backgroundColor: ['rgba(55, 125, 255, 0)', 'rgba(255, 255, 255, 0)'],
borderColor: '#377dff',
borderWidth: 2,
pointRadius: 0,
pointHoverRadius: 0
}
]
},
options: {
scales: {
yAxes: [
{
display: false
}
],
xAxes: [
{
display: false
}
]
},
hover: {
mode: 'nearest',
intersect: false
},
tooltips: {
postfix: '%',
hasIndicator: false,
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();
});
};
$(document).on('ready', function() {
getChartData();
// 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));
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.4"></script>
<!-- as you are using v2.x of chart.js -->
<canvas id="occChart" width="640" height="480"></canvas>
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>
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:
code for chart.js v2.9.4 (latest for v2.x)
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>
class AreaChart extends React.Component {
constructor(props) {
super(props);
this.state = {
chartData: CHART_DATA,
chartDataSelection: CHART_DATA.selection
};}
My CHART_DATA is my object and I assigned it to chartData.
Below is my updateData function. This is where I am having a problem. Under this.setState, chartDataSelection is not grabbing the data from my object. I don't know how to properly grab the selection key from the CHART_DATA object. Below this code is the other js file that holds that object.
updateData(timeline) {
this.setState({
chartDataSelection: timeline
});
switch (timeline) {
case "one_month":
this.setState({
options: {
xaxis: {
min: new Date("28 Jan 2013").getTime(),
max: new Date("27 Feb 2013").getTime()
}
}
});
break;
case "six_months":
this.setState({
options: {
xaxis: {
min: new Date("27 Sep 2012").getTime(),
max: new Date("27 Feb 2013").getTime()
}
}
});
break;
case "one_year":
this.setState({
options: {
xaxis: {
min: new Date("27 Feb 2012").getTime(),
max: new Date("27 Feb 2013").getTime()
}
}
});
break;
case "ytd":
this.setState({
options: {
xaxis: {
min: new Date("01 Jan 2013").getTime(),
max: new Date("27 Feb 2013").getTime()
}
}
});
break;
case "all":
this.setState({
options: {
xaxis: {
min: undefined,
max: undefined
}
}
});
break;
default:
}
}
CHART_DATA.js --- this data is for my Area Chart from ApexCharts
const CHART_DATA = {
coins: "hello",
isFetching: false,
selection: "one_year", // this data is for the ReactApexChart line 14-395
options: {
annotations: {
yaxis: [
{
y: 0,
tickAmount: 0,
borderColor: "transparent",
label: {
borderColor: "red",
show: false,
showAlways: false,
style: {
color: "#fff",
background: "#00E396"
}
},
floating: true,
axisTicks: {
show: false
},
axisBorder: {
show: false
},
labels: {
show: false
},
crosshairs: {
show: false
}
}
],
xaxis: [
{
x: new Date("14 Nov 2012").getTime(),
borderColor: "transparent",
yAxisIndex: 0,
label: {
show: false,
text: "",
style: {
color: "#fff",
background: "#775DD0"
}
},
axisTicks: {
show: false
}
}
]
},
dataLabels: {
enabled: false,
enabledOnSeries: false
},
markers: {
size: 0,
style: "hollow"
},
xaxis: {
type: "datetime",
min: new Date("01 Mar 2012").getTime(),
tickAmount: 6
},
tooltip: {
x: {
format: "MMMM dd yyyy"
}
},
fill: {
type: "gradient",
gradient: {
shadeIntensity: 1,
opacityFrom: 0.3,
opacityTo: 0.9,
stops: [0, 100]
}
},
colors: ["#6433ff", "#00E396", "#CED4DC"],
stroke: {
width: "2"
},
chart: {
toolbar: {
show: false,
tools: {
download: true,
selection: true,
zoom: true,
zoomin: true,
zoomout: true,
pan: true,
reset: true | '<img src="/static/icons/reset.png" width="20">',
customIcons: []
},
autoSelected: "zoom"
}
}
},
series: [
{
//timestamps for the areaChart
data: [
[1327359600000, 30.95],
[1327446000000, 31.34],
[1327532400000, 31.18],
[1327618800000, 31.05],
[1327878000000, 31.0],
[1327964400000, 30.95],
[1328050800000, 31.24],
[1328137200000, 31.29],
[1328223600000, 31.85],
[1328482800000, 31.86],
[1328569200000, 32.28],
[1328655600000, 32.1],
[1328742000000, 32.65],
[1328828400000, 32.21],
[1329087600000, 32.35],
[1329174000000, 32.44],
[1329260400000, 32.46],
[1329346800000, 32.86],
[1329433200000, 32.75],
[1329778800000, 32.54],
[1329865200000, 32.33],
[1329951600000, 32.97],
[1330038000000, 33.41],
[1330297200000, 33.27],
[1330383600000, 33.27],
[1330470000000, 32.89],
[1330556400000, 33.1],
[1330642800000, 33.73],
[1330902000000, 33.22],
[1330988400000, 31.99],
[1331074800000, 32.41],
[1331161200000, 33.05],
[1331247600000, 33.64],
[1331506800000, 33.56],
[1331593200000, 34.22],
[1331679600000, 33.77],
[1331766000000, 34.17],
[1331852400000, 33.82],
[1332111600000, 34.51],
[1332198000000, 33.16],
[1332284400000, 33.56],
[1332370800000, 33.71],
[1332457200000, 33.81],
[1332712800000, 34.4],
[1332799200000, 34.63],
[1332885600000, 34.46],
[1332972000000, 34.48],
[1333058400000, 34.31],
[1333317600000, 34.7],
[1333404000000, 34.31],
[1333490400000, 33.46],
[1333576800000, 33.59],
[1333922400000, 33.22],
[1334008800000, 32.61],
[1334095200000, 33.01],
[1334181600000, 33.55],
[1334268000000, 33.18],
[1334527200000, 32.84],
[1334613600000, 33.84],
[1334700000000, 33.39],
[1334786400000, 32.91],
[1334872800000, 33.06],
[1335132000000, 32.62],
[1335218400000, 32.4],
[1335304800000, 33.13],
[1335391200000, 33.26],
[1335477600000, 33.58],
[1335736800000, 33.55],
[1335823200000, 33.77],
[1335909600000, 33.76],
[1335996000000, 33.32],
[1336082400000, 32.61],
[1336341600000, 32.52],
[1336428000000, 32.67],
[1336514400000, 32.52],
[1336600800000, 31.92],
[1336687200000, 32.2],
[1336946400000, 32.23],
[1337032800000, 32.33],
[1337119200000, 32.36],
[1337205600000, 32.01],
[1337292000000, 31.31],
[1337551200000, 32.01],
[1337637600000, 32.01],
[1337724000000, 32.18],
[1337810400000, 31.54],
[1337896800000, 31.6],
[1338242400000, 32.05],
[1338328800000, 31.29],
[1338415200000, 31.05],
[1338501600000, 29.82],
[1338760800000, 30.31],
[1338847200000, 30.7],
[1338933600000, 31.69],
[1339020000000, 31.32],
[1339106400000, 31.65],
[1339365600000, 31.13],
[1339452000000, 31.77],
[1339538400000, 31.79],
[1339624800000, 31.67],
[1339711200000, 32.39],
[1339970400000, 32.63],
[1340056800000, 32.89],
[1340143200000, 31.99],
[1340229600000, 31.23],
[1340316000000, 31.57],
[1340575200000, 30.84],
[1340661600000, 31.07],
[1340748000000, 31.41],
[1340834400000, 31.17],
[1340920800000, 32.37],
[1341180000000, 32.19],
[1341266400000, 32.51],
[1341439200000, 32.53],
[1341525600000, 31.37],
[1341784800000, 30.43],
[1341871200000, 30.44],
[1341957600000, 30.2],
[1342044000000, 30.14],
[1342130400000, 30.65],
[1342389600000, 30.4],
[1342476000000, 30.65],
[1342562400000, 31.43],
[1342648800000, 31.89],
[1342735200000, 31.38],
[1342994400000, 30.64],
[1343080800000, 30.02],
[1343167200000, 30.33],
[1343253600000, 30.95],
[1343340000000, 31.89],
[1343599200000, 31.01],
[1343685600000, 30.88],
[1343772000000, 30.69],
[1343858400000, 30.58],
[1343944800000, 32.02],
[1344204000000, 32.14],
[1344290400000, 32.37],
[1344376800000, 32.51],
[1344463200000, 32.65],
[1344549600000, 32.64],
[1344808800000, 32.27],
[1344895200000, 32.1],
[1344981600000, 32.91],
[1345068000000, 33.65],
[1345154400000, 33.8],
[1345413600000, 33.92],
[1345500000000, 33.75],
[1345586400000, 33.84],
[1345672800000, 33.5],
[1345759200000, 32.26],
[1346018400000, 32.32],
[1346104800000, 32.06],
[1346191200000, 31.96],
[1346277600000, 31.46],
[1346364000000, 31.27],
[1346709600000, 31.43],
[1346796000000, 32.26],
[1346882400000, 32.79],
[1346968800000, 32.46],
[1347228000000, 32.13],
[1347314400000, 32.43],
[1347400800000, 32.42],
[1347487200000, 32.81],
[1347573600000, 33.34],
[1347832800000, 33.41],
[1347919200000, 32.57],
[1348005600000, 33.12],
[1348092000000, 34.53],
[1348178400000, 33.83],
[1348437600000, 33.41],
[1348524000000, 32.9],
[1348610400000, 32.53],
[1348696800000, 32.8],
[1348783200000, 32.44],
[1349042400000, 32.62],
[1349128800000, 32.57],
[1349215200000, 32.6],
[1349301600000, 32.68],
[1349388000000, 32.47],
[1349647200000, 32.23],
[1349733600000, 31.68],
[1349820000000, 31.51],
[1349906400000, 31.78],
[1349992800000, 31.94],
[1350252000000, 32.33],
[1350338400000, 33.24],
[1350424800000, 33.44],
[1350511200000, 33.48],
[1350597600000, 33.24],
[1350856800000, 33.49],
[1350943200000, 33.31],
[1351029600000, 33.36],
[1351116000000, 33.4],
[1351202400000, 34.01],
[1351638000000, 34.02],
[1351724400000, 34.36],
[1351810800000, 34.39],
[1352070000000, 34.24],
[1352156400000, 34.39],
[1352242800000, 33.47],
[1352329200000, 32.98],
[1352415600000, 32.9],
[1352674800000, 32.7],
[1352761200000, 32.54],
[1352847600000, 32.23],
[1352934000000, 32.64],
[1353020400000, 32.65],
[1353279600000, 32.92],
[1353366000000, 32.64],
[1353452400000, 32.84],
[1353625200000, 33.4],
[1353884400000, 33.3],
[1353970800000, 33.18],
[1354057200000, 33.88],
[1354143600000, 34.09],
[1354230000000, 34.61],
[1354489200000, 34.7],
[1354575600000, 35.3],
[1354662000000, 35.4],
[1354748400000, 35.14],
[1354834800000, 35.48],
[1355094000000, 35.75],
[1355180400000, 35.54],
[1355266800000, 35.96],
[1355353200000, 35.53],
[1355439600000, 37.56],
[1355698800000, 37.42],
[1355785200000, 37.49],
[1355871600000, 38.09],
[1355958000000, 37.87],
[1356044400000, 37.71],
[1356303600000, 37.53],
[1356476400000, 37.55],
[1356562800000, 37.3],
[1356649200000, 36.9],
[1356908400000, 37.68],
[1357081200000, 38.34],
[1357167600000, 37.75],
[1357254000000, 38.13],
[1357513200000, 37.94],
[1357599600000, 38.14],
[1357686000000, 38.66],
[1357772400000, 38.62],
[1357858800000, 38.09],
[1358118000000, 38.16],
[1358204400000, 38.15],
[1358290800000, 37.88],
[1358377200000, 37.73],
[1358463600000, 37.98],
[1358809200000, 37.95],
[1358895600000, 38.25],
[1358982000000, 38.1],
[1359068400000, 38.32],
[1359327600000, 38.24],
[1359414000000, 38.52],
[1359500400000, 37.94],
[1359586800000, 37.83],
[1359673200000, 38.34],
[1359932400000, 38.1],
[1360018800000, 38.51],
[1360105200000, 38.4],
[1360191600000, 38.07],
[1360278000000, 39.12],
[1360537200000, 38.64],
[1360623600000, 38.89],
[1360710000000, 38.81],
[1360796400000, 38.61],
[1360882800000, 38.63],
[1361228400000, 38.99],
[1361314800000, 38.77],
[1361401200000, 38.34],
[1361487600000, 38.55],
[1361746800000, 38.11],
[1361833200000, 38.59],
[1361919600000, 39.6]
]
}
]
};
export default CHART_DATA;
It looks like you aren't telling setState to update your chartData (setState{chartData: {updatedData}}) but creating a new state object called options. First you need modify the existing charData. In this case I've spread it out into a variable called data. Then you modify data with the new xaxis and then replace chartData completely with your updated object. I've shortened your switch just for the example but you will have to update each of them. I hope this helps.
updateData(timeline) {
this.setState({
chartDataSelection: timeline
});
let data = {...d}
switch (timeline) {
case "one_month":
data.options.xaxis = {
min: new Date("28 Jan 2013").getTime(),
max: new Date("27 Feb 2013").getTime()
}
this.setState({chartData: data});
break;
default:
}
}