ChartJS with multiple axis custom tooltip not working - chart.js

I'm using the latest version of the chartJS on my Angular 5 application but when I try to call the custom tooltip using the options and the custom function nothing happens.
I added a console.log to see if the function gets called but I do not see it.
Here is my options object.
this.chartOptions = {
responsive: true,
maintainAspectRatio: false,
title: {
display: true,
text: '',
fontStyle: 'bold'
},
animation: {
duration: 0
},
hover: {
animationDuration: 0,
mode: 'nearest',
intersect: true
},
responsiveAnimationDuration: 0,
elements: {
line: {
tension: 0
},
point: {
radius: 5
}
},
scales: {
xAxes: [
{
scaleLabel: {
display: true,
labelString: 'Year',
fontStyle: 'bold'
}
}
],
yAxes: [
{
id: 'y-axis-1',
display: true,
position: 'left',
type: 'linear',
scaleLabel: {
display: true,
labelString: (this.chartUnit === 'U') ? 'Sales (Units)' : 'Sales (USD)',
fontStyle: 'bold'
},
stacked: false,
ticks: {
callback: function(value, index, values) {
const prefix = self.chartUnit === 'D' ? '$' : self.chartUnit === 'P' ? '%' : '';
const numValue = value.toLocaleString();
if (self.chartUnit === 'P') {
return numValue + prefix;
} else {
return prefix + numValue;
}
},
fontStyle: 'bold'
}
},
{
id: 'y-axis-2',
display: true,
position: 'right',
type: 'linear',
gridLines: {
display: true,
drawBorder: true,
drawOnChartArea: false
},
scaleLabel: {
display: true,
labelString: (this.chartUnit === 'U') ? 'Total Sales (Units)' : 'Total Sales (USD)',
fontStyle: 'bold'
},
stacked: false,
ticks: {
callback: function(value, index, values) {
const prefix = self.chartUnit === 'D' ? '$' : self.chartUnit === 'P' ? '%' : '';
const numValue = value.toLocaleString();
if (self.chartUnit === 'P') {
return numValue + prefix;
} else {
return prefix + numValue;
}
},
fontStyle: 'bold'
}
}
]
},
tooltip: {
mode: 'nearest',
custom: function() {
console.log('hello');
}
}
}

Related

How to show label for second y-axis in charts.js?

I have two y-axis in my charts.js scatter chart, and all my data is displayed correctly.
However, whilst the label for the first y-axis is showing, the label for the second y-axis is not.
Here's my code:
window.laChart = new Chart(ctx, {
type: 'scatter',
data: {
datasets: allDatasets
},
options: {
scales: {
xAxes: [{
scaleLabel: {
display: true,
labelString: X_AXIS_LABEL
},
ticks: {
min: 0,
max: 18,
stepSize: 1,
// Format the x-axis values
callback: function(value, index, values) {
return value;// + ".000";
}
},
gridLines: {
display: false
}
}],
yAxes: [
{
ticks: {
beginAtZero: true,
min: 0,
max: 100
},
position: "left",
id: "y-axis-1",
type: "linear"
},
{
ticks: {
beginAtZero: true,
min: 0,
suggestedMax: 10
},
position: "right",
id: "y-axis-2",
type: "linear"
},
{
gridLines: {
display: false
},
ticks: {
maxTicksLimit: 3, // This will give us a top tick, middle tick and bottom tick.
callback: function(value, index) {
if (index === 1) { // This is the middle tick.
return Y1_AXIS_LABEL;
}
else {
return '';
}
}
}
}]
}
}
And here's a screenshot with the second y-axis label missing:
How do I make the label for the second y-axis appear?
SOLUTION
LeeLenalee's answer worked, but it left me with rotated labelStrings. I adapted his answer to solve this issue with this final code:
yAxes: [
{
ticks: {
beginAtZero: true,
min: 0,
max: 100
},
scaleLabel: {
display: false,
labelString: Y1_AXIS_LABEL
},
position: "left",
id: "y-axis-1",
type: "linear"
},
{
ticks: {
beginAtZero: true,
min: 0
},
scaleLabel: {
display: false,
labelString: Y2_AXIS_LABEL
},
position: "right",
id: "y-axis-2",
type: "linear"
},
// Change the orientation of the first y-axis label.
{
gridLines: {
display: false
},
ticks: {
maxTicksLimit: 3, // This will give us a top tick, middle tick and bottom tick.
callback: function(value, index) {
if (index === 1) { // This is the middle tick.
return Y1_AXIS_LABEL;
}
else {
return '';
}
}
},
position: "left"
},
// Change the orientation of the second y-axis label.
{
gridLines: {
display: false
},
ticks: {
maxTicksLimit: 3, // This will give us a top tick, middle tick and bottom tick.
callback: function(value, index) {
if (index === 1) { // This is the middle tick.
return Y2_AXIS_LABEL;
}
else {
return '';
}
}
},
position: "right"
}
]
Final screenshot:
What you did is implement a new scale as replacement for the scale label, this is not the way you should do it because the scale will only be on the left. You have to use the scalelabel as you did with the X axis for both yAxes like this:
yAxes: [
{
ticks: {
beginAtZero: true,
min: 0,
max: 100
},
scaleLabel: {
display: true,
labelString: Y1_AXIS_LABEL
},
position: "left",
id: "y-axis-1",
type: "linear"
},
{
ticks: {
beginAtZero: true,
min: 0,
suggestedMax: 10
},
scaleLabel: {
display: true,
labelString: Y2_AXIS_LABEL
},
position: "right",
id: "y-axis-2",
type: "linear"
}]

increase the gap between y-axis and first x-axis value chart.js

I want to display points in the line chart of chart.js, however, points one first and the last index at x-axis don't show up completely as shown in the image
How can I increase the gap between the first and last values of x-axis from the y-axis. Here is my code for the chart
var config = {
type: 'line',
data: {
labels: ['1809_1970', '1971_1975', '1976_1980', '1981_1985', '1986_1990', '1991_1995', '1996_2000','2001_2005','2006_2010','2011_2012','2013_2015'],
datasets: [d1,d2,d3]
},
options: {
responsive: true,
title: {
display: true,
text: 'points chart',
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var label = data.datasets[tooltipItem.datasetIndex].cui[tooltipItem.xLabel] || '';
return 'CUI'+' :: '+label ;
},
afterLabel: function(tooltipItem, data) {
var cui_name = data.datasets[tooltipItem.datasetIndex].cui_name[tooltipItem.xLabel] || '';
return ['NAME'+' :: '+cui_name];
}
}
},
hover: {
mode: 'index',
intersect: true
},
pan: {
enabled: true,
mode: 'y'
},
zoom: {
enabled: true,
mode: 'y',
speed: 0.025
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Time Frame'
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Score'
}
}]
}
}
};
I needed to accomplish the same thing, and I was able to get the desired result bby adding offset: true to the xAxes options.
xAxes: [{
offset: true, // <-- This right here
display: true,
scaleLabel: {
display: true,
labelString: 'Time Frame'
}
}],

Chartjs: Overlapping values when using Datalabels plugin

I am using the datalabels plugin, and the values overlap if they are too long:
I tried using the diaply auto under plugins datalabels, but it stills overlaps, any ideas what to do so that they dont overlap?
here are my options:
const getOptions = (yAxisDisplayLabel, data, previousOpts, isMobile) => ({
...previousOpts,
layout: {
padding: {
top: 20,
},
},
plugins: {
datalabels: {
font: {
size: isMobile ? 8 : 12,
},
offset: isMobile ? -15 : -20,
anchor: 'end',
formatter: (value, context) => data.datasets[context.datasetIndex].displayValue[context.dataIndex],
display: 'auto',
align: 'start',
},
},
scales: {
yAxes: [{
ticks: {
display: true,
fontColor: '#c8c8c8',
fontSize: isMobile ? 8 : 12,
fontFamily: 'Futura Book',
beginAtZero: true,
},
gridLines: {
drawBorder: false,
},
scaleLabel: {
display: true,
labelString: yAxisDisplayLabel,
},
}],
xAxes: [{
categoryPercentage: isMobile ? 0.8 : 0.7,
barPercentage: 1,
gridLines: {
display: false,
drawBorder: false,
},
}],
},
legend: {
display: false,
},
scaleBeginAtZero: true,
});
The simple, non-technical, answer is of course to write Unit: €/m2 somewhere else on the chart and not an every bar.

AutoSkip: False not working on time xAxes labels

I have a bar chart, which is autoSkipping every second xAxes labels. I need to show all labels, however setting AutoSkip: False is having no effect.
Below is my code, I have removed some extra datasets from it.
var myChart2 = new Chart(document.getElementById("ch2"), {
type: 'bar',
data: {
datasets: [
{
label: 'Budget',
data: [<data here>]
}
]
},
options: {
tooltips: {
callbacks: {
label: function (tooltipItem, data) {
return '$' + tooltipItem.yLabel;
}
}
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
callback: function (value, index, values) {
return '$' + (value >= 1000000 ? value/1000000+'M' : value);
}
},
stacked: true
}],
xAxes: [{
type: "time",
ticks: {
autoSkip: false // Not working
},
time: {
unit: 'month',
format: 'DD MMM YYYY',
tooltipFormat: 'MMM YYYY',
displayFormats: {
month: 'MMM'
}
},
offset: true,
gridLines: {
display: false,
offsetGridLines: true
}
}]
}
}
});
In my case, I needed to set source: date. You will get all the date steps on xAxi. By the way, try source: auto it'll try set optimal count of steps (not all). Check here https://www.chartjs.org/docs/latest/axes/cartesian/time.html#ticks-source

How to Create a Custom Logarithmic Axis in Chart.js

I'm trying to refactor an old Flex app using Chart.js and I would like to replicate this linear/log axis. Notice the clean minimal spacing on the yAxis.
Here is my Chart.js code.
var mtbsoData = [];
var mtbsoLables = [];
for (let i = 0; i <= 10; i++) {
mtbsoData.push(i * i * i * i);
mtbsoLables.push(i.toString());
}
var ctxMtbso = document.getElementById("chartMtbso").getContext('2d');
var chartMtbso = new Chart(ctxMtbso, {
type: 'bar',
data: {
labels: mtbsoLables,
datasets: [{
label: 'label',
data: mtbsoData,
backgroundColor: 'rgba(0, 0, 255, .6)',
borderColor: 'rgba(0, 0, 255, 1)',
borderWidth: 1
}]
},
options: {
title: {
text: 'Title',
display: true,
fontSize: 24
},
scales: {
xAxes: [{
display: true,
ticks: {
beginAtZero: true
},
scaleLabel: {
display: true,
labelString: 'X Axis'
}
}],
yAxes: [{
type: 'logarithmic',
ticks: {
min: 0,
max: 1000,
callback: function (value, index, values) {
return value + ' years';
}
},
scaleLabel: {
display: true,
labelString: 'Y Axis'
}
}]
},
tooltips: {
callbacks: {
label: function (tooltipItem, data) {
var label = data.datasets[tooltipItem.datasetIndex].label || '';
if (label) {
label += ': ';
}
label += tooltipItem.yLabel.toFixed(2);
return label;
}
}
},
legend: {
display: false
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<canvas id="chartMtbso"></canvas>
Here's a screenshot. Notice the crowded ticks on the yAxis.
It seems from the documentation that the only ticks properties that you can apply are the "min" and "max" properties.
Can anybody suggest a solution?
I fixed it.
Modify the yAxes callback as shown:
yAxes: [{
type: 'logarithmic',
ticks: {
autoSkip: true,
min: 0,
callback: function (value, index, values) {
if( value==10 || value==100 || value==1000 || value==10000 || value==100000 || value==1000000){
return value + ' years';
}
}
},
scaleLabel: {
display: true,
labelString: 'Mean Time Between Stock-Out'
}
}]
Then you only return a tick if the value is a power of ten.