Chart.js legend configuration options not working [duplicate] - javascript

I am trying to hide the legend of my chart created with Chart.js.
According to the official documentation (https://www.chartjs.org/docs/latest/configuration/legend.html), to hide the legend, the display property of the options.display object must be set to false.
I have tried to do it in the following way:
const options = {
legend: {
display: false,
}
};
But it doesn't work, my legend is still there. I even tried this other way, but unfortunately, without success.
const options = {
legend: {
display: false,
labels: {
display: false
}
}
}
};
This is my full code.
import React, { useEffect, useState } from 'react';
import { Line } from "react-chartjs-2";
import numeral from 'numeral';
const options = {
legend: {
display: false,
},
elements: {
point: {
radius: 1,
},
},
maintainAspectRatio: false,
tooltips: {
mode: "index",
intersect: false,
callbacks: {
label: function (tooltipItem, data) {
return numeral(tooltipItem.value).format("+0,000");
},
},
},
scales: {
xAxes: [
{
type: "time",
time: {
format: "DD/MM/YY",
tooltipFormat: "ll",
},
},
],
yAxes: [
{
gridLines: {
display: false,
},
ticks: {
callback: function(value, index, values) {
return numeral(value).format("0a");
},
},
},
],
},
};
const buildChartData = (data, casesType = "cases") => {
let chartData = [];
let lastDataPoint;
for(let date in data.cases) {
if (lastDataPoint) {
let newDataPoint = {
x: date,
y: data[casesType][date] - lastDataPoint
}
chartData.push(newDataPoint);
}
lastDataPoint = data[casesType][date];
}
return chartData;
};
function LineGraph({ casesType }) {
const [data, setData] = useState({});
useEffect(() => {
const fetchData = async() => {
await fetch("https://disease.sh/v3/covid-19/historical/all?lastdays=120")
.then ((response) => {
return response.json();
})
.then((data) => {
let chartData = buildChartData(data, casesType);
setData(chartData);
});
};
fetchData();
}, [casesType]);
return (
<div>
{data?.length > 0 && (
<Line
data={{
datasets: [
{
backgroundColor: "rgba(204, 16, 52, 0.5)",
borderColor: "#CC1034",
data: data
},
],
}}
options={options}
/>
)}
</div>
);
}
export default LineGraph;
Could someone help me? Thank you in advance!
PD: Maybe is useful to try to find a solution, but I get 'undefined' in the text of my legend and when I try to change the text like this, the text legend still appearing as 'Undefindex'.
const options = {
legend: {
display: true,
text: 'Hello!'
}
};

As described in the documentation you linked the namespace where the legend is configured is: options.plugins.legend, if you put it there it will work:
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'pink'
}
]
},
options: {
plugins: {
legend: {
display: false
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.0/chart.js"></script>
</body>
On another note, a big part of your options object is wrong, its in V2 syntax while you are using v3, please take a look at the migration guide
Reason why you get undefined as text in your legend is, is because you dont supply any label argument in your dataset.

in the newest versions this code works fine
const options = {
plugins: {
legend: {
display: false,
},
},
};
return <Doughnut data={data} options={options} />;

Import your options value inside the charts component like so:
const options = {
legend: {
display: false
}
};
<Line data={data} options={options} />

Related

Equivalent of $.fn. of jQuery in Vanilla JS

Last few days I've been trying to convert this code to pure JS, but no luck until now...
This code basically starts a new Chart.JS instance when called via jQuery object.
(function ($) {
$.fn.createChartLine = function (labels, datasets, options) {
var settings = $.extend({}, $.fn.createChartLine.defaults, options);
this.each(function () {
let ctx = $(this);
new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: datasets
},
options: {
scales: {
y: {
title: {
display: true,
text: settings.labelString
},
beginAtZero: true
}
},
plugins: {
legend: {
display: settings.display_legend,
position: settings.legend_position,
labels: {
usePointStyle: settings.legend_pointStyle
}
}
}
}
});
});
};
$.fn.createChartLine.defaults = {
display_legend: true,
legend_position: 'top',
legend_pointStyle: true,
labelString: 'Clicks'
};
})(jQuery);
The initialization of a new chartline using the code above:
$("#chart1").createChartLine(['1', '2', '3'], [{
label: 'Clicks',
backgroundColor: Chart.helpers.color('#007bff').alpha(0.75).rgbString(),
borderColor: '#007bff',
data: [34, 56, 28],
borderWidth: 2,
tension: 0.4
}], {display_legend: false});
I tried thousands of ways to remove jQuery from it, but no luck. The intention is to get rid of jQuery in some pages, but this script is essential because with it I can create many Chart.JS instances in same page without needing repeating that amount of code.
I'm aiming to get something like this:
document.getElementById('chart1').createChartLine(...);
Is it possible?
This assumes you are using a version of ChartJS that accepts HTMLCanvasElement and other non-jQuery wrapped Elements to the new Chart() constructor.
You shouldn't extend the prototype of native elements, instead you should create a new function that gets the element(s) passed in.
// Instead of
document.getElementById('chart1').createChartLine(...);
// You'll want
createChartLine(document.getElementById('chart1'), ...);
or something similar.
I'd actually not pass in the element, but rather a selector, since that most closely matches how the jQuery plugin is working.
function createChartLine(selector, labels, datasets, options = {}) {
const settings = Object.assign(
{},
{
display_legend: true,
legend_position: "top",
legend_pointStyle: true,
labelString: "Clicks",
},
options
);
const elements = document.querySelectorAll(selector);
const charts = [];
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
const newChart = new Chart(element, {
type: "line",
data: {
labels: labels,
datasets: datasets,
},
options: {
scales: {
y: {
title: {
display: true,
text: settings.labelString,
},
beginAtZero: true,
},
},
plugins: {
legend: {
display: settings.display_legend,
position: settings.legend_position,
labels: {
usePointStyle: settings.legend_pointStyle,
},
},
},
},
});
charts.push(newChart);
}
return charts;
}
Here is how you'd call the function.
createChartLine(
"#chart1", // This is the new argument, the selector of the element you are initializing
["1", "2", "3"],
[
{
label: "Clicks",
backgroundColor: Chart.helpers.color("#007bff").alpha(0.75).rgbString(),
borderColor: "#007bff",
data: [34, 56, 28],
borderWidth: 2,
tension: 0.4,
},
],
{ display_legend: false }
);

Vue Chart JS options aren't used

I'm using Vue Chart JS v3.5.1 in my Nuxt JS/Vue project, and I've noticed that when trying to use options and pass them as a prop, nothing happens, the chart defaults back to the chart's default settings despite me overwriting settings.
I've got several files:
plugins/LineChart.js
components/LineChart.vue
plugins/LineChart.js
import { Line, mixins } from 'vue-chartjs'
const { reactiveProp } = mixins
export default {
extends: Line,
mixins: [reactiveProp],
computed: {
localOptions: function() {
return this.chartOptions
},
localData: function() {
console.log(`data: ${this.chartData}`)
return this.chartData
}
},
mounted () {
this.renderLineChart()
},
methods: {
/*
** Render a line chart
*/
renderLineChart () {
// this.chartdata is created in the mixin.
// If you want to pass options please create a local options object
this.renderChart(this.localData, this.localOptions)
}
},
watch: {
chartData: {
handler: function (val, oldVal) {
this._data._chart.destroy()
this.renderLineChart()
},
deep: true
},
chartOptions: {
handler: function (val, oldVal) {
this.localOptions = val
},
deep: true
}
}
}
components/LineChart.vue
<template>
<div>
<line-chart :chart-data="customChartData" :chart-options="customChartOptions" class="data-chart"></line-chart>
</div>
</template>
<style>
.data-chart canvas {
width: 100% !important;
height: auto !important;
}
</style>
<script>
import LineChart from '~/plugins/LineChart.js'
export default {
components: {
LineChart
},
props: {
labels: {
type: Array,
default: null
},
datasets: {
type: Array,
default: null
},
options: {
type: Object,
default: () => ({})
}
},
data () {
return {
customChartData: {},
customChartOptions: {}
}
},
mounted () {
this.fillData()
},
methods: {
fillData () {
this.customChartData = {
labels: this.labels,
datasets: this.datasets
}
this.customChartOptions = {
options: this.options
}
}
}
}
</script>
My usage, is then reasonably simple, yet I'm not getting my options to show?
<LineChart
:options="{
responsive: true,
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
xAxes: [{
gridLines: {
display: false
},
ticks: {
autoSkip: true,
maxTicksLimit: 3,
maxRotation: 0,
minRotation: 0
}
}],
yAxes: [{
display: true,
gridLines: {
display: true,
color: '#f3f5f6'
}
}]
},
elements: {
point: {
radius: 0,
hitRadius: 35
}
}
}"
:labels="['test']"
:datasets="[{
fill: false,
borderWidth: 2.5,
pointBackgroundColor: '#fff',
borderColor: '#5046e5',
data: [500,
}]"
/>
What am I doing wrong?
UPDATE
In addition, I seem to only have the first chart out of many charts on the page show data, why would only one chart in a series of charts show data, I've got a key on each one.
in your fillData it looks like you assign the options wrong. Vue Chartjs expects an object with the options in it and not an object with an field options with the options.
If you change: this.customChartOptions = {options: this.options} to: this.customChartOptions = this.options it should work

ChartJS with React: Only one value showing on time chart

I am creating a cryptocurrency price tracker with React. I am using axios to make API requests and get information about the price history of different cryptocurrencies. This works fine, but when I am creating the chart with ChartJS, the chart only shows one value, even though I have thousands. Anyone know how to fix this? Big thanks in advance.
Here is my code for the chart component:
import Chartjs from "chart.js";
import axios from "axios";
import { historyOptions } from "../../chartConfigs/chartConfigs";
const HistoryChart = ({ coinId }) => {
const [timeLength, setTimeLength] = useState(30);
const chartRef = useRef();
const [timeSeriesData, setTimeSeriesData] = useState([]);
useEffect(() => {
const timeSeriesDataArray = [];
axios.get(`https://api.coingecko.com/api/v3/coins/${coinId}/market_chart?vs_currency=usd&days=${30}`)
.then(response => {
response.data.prices.forEach(element => {
timeSeriesDataArray.push(
{
t: element[0],
y: element[2].toFixed(2)
}
)
})
setTimeSeriesData(timeSeriesDataArray)
})
.catch(error => console.log(error))
}, [coinId, timeLength])
useEffect(() => {
if (chartRef && chartRef.current) {
const chartInstance = new Chartjs(chartRef.current,{
type: 'line',
data: {
datasets: [{
label: "Price",
data: timeSeriesData,
backgroundColor: "rgba(174, 374, 194, 0.5)",
borderColor: "rgba(174, 374, 194, 0.4)",
pointRadius: 0,
borderWidth: 1
}]
},
options: historyOptions
})
}
}, [timeSeriesData])
return (
<div className="history-chart-container">
<canvas ref={chartRef} id="history-chart" width={1200} height={500}></canvas>
</div>
)
}
export default HistoryChart
Here is my code for the chart options (historyOptions):
lineHeighAnnotation: {
always: true,
hover: false,
lineHeight: 1.5
},
animation: {
duration: 2000
},
maintainAspectRatio: false,
responsive: true,
scales: {
xAxes: {
type: "time",
distribution: "linear",
}
}
}```
[1]: https://i.stack.imgur.com/e7g4P.png
[2]: https://i.stack.imgur.com/t4YIa.png
This could be fixed by changing your line chart into a scatter chart.
const chartInstance = new Chartjs(chartRef.current,{
type: 'scatter',
...
To still get the lines drawn between the data points, you need to define the option showLine: true on the dataset.
datasets: [{
label: "Price",
showLine: true,
...
}]
UPDATE
You should also make sure to update the chart when new data is added and the chart already exists. Not knowing much about react.js, you could make chartInstance a global variable and proceed as follows:
if (chartRef && chartRef.current) {
chartInstance = new Chartjs(chartRef.current,{
type: 'line',
...
} else {
chartInstance.update();
}

chart js when hover shows old values

When Dropdown selected change ıt shows previous selected values. I tried many ways like destroy the chart functionality but none of them work or I am not able to work it
any one can help me about the solution.
I have saw many answers about this question but none of them works ..
I have shared my code below so looking for help
let asyaIlceRuhsat = document.getElementById('asyaIlceRuhsat').getContext('2d');
$(document).ready(function () {
$('#mySelectAsya').select2({
width: '100%'
}).val() == -1 ? $('#asyaIlceRuhsat').after('<div class="asyaSecimi"><p class="text-center text-uppercase font-weight-bolder">Lütfen ilçe seçiniz!</p></div>') : null;
});
//Asya Yakası
$('#mySelectAsya').on('select2:select', function (e) {
var selectedId = $('#mySelectAsya').val()
var selectedText = $("#mySelectAsya :selected").text()
var canvas = document.getElementById('asyaIlceRuhsat')
if (selectedId === -1) {
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
$(".asyaSecimi").css("display", "block");
$(canvas).addClass("hidden");
}
else {
$(canvas).removeClass("hidden");
$(".asyaSecimi").css("display", "none");
}
fetch(`http://myurl/api/Web/Test/GetValue?query=${queryId}`)
.then(function (response) {
return response.json();
// console.log(response)
})
.then(function (ids) {
// console.info(`ids:`, ids)
new Chart(asyaIlceRuhsat, {
type: 'bar',
data: {
labels: ids.map(function (id) {
return id.TUR;
}),
datasets: [
{
label: "ARIZA",
backgroundColor: "#e65c00",
data: ids.map(function (id) {
return id.ARIZASAYISI;
}),
}, {
label: "ARIZA ONAY",
backgroundColor: "#66ff66",
data: ids.map(function (id) {
return id.ARIZAONAYSAYISI;
}),
}, {
label: "NORMAL",
backgroundColor: "#66ccff",
data: ids.map(function (id) {
return id.NORAMLSAYISI;
}),
}, {
label: "BAŞVURU",
backgroundColor: "#0099ff",
data: ids.map(function (id) {
return id.BASVURUSAYISI;
}),
},
]
},
options: {
title: {
display: true,
text: 'Normal Ruhsat Durum',
fontSize: 18
},
legend: {
display: true,
position: 'right',
labels: {
fontColor: '#000',
usePointStyle: false
}
},
layout: {
padding: {
left: 0,
right: 0,
bottom: 0,
top: 0
}
},
scales: {
xAxes: [{
scaleLabel: {
display: true,
labelString: 'Asya Geneli Normal Ruhsat Durumları',
fontColor: '#000000',
fontSize: 12
}
}]
}
}
});
});
})
This is a very common issue while updating the same canvas with a new chart. On your dropdown change event try to add the following code which will destroy all the charts previous instance.
Chart.helpers.each(Chart.instances, function (instance) {
instance.destroy();
});

Handle zero values in react-chartjs-2

i'm using react-chartjs-2 for customizing three donut pie charts. This library is amazing with many functionalities but i'm having a problem here. I dont know how to handle zero values. When all my values are zero not pie chart is drawn which is correct. Any ideas of how to handle zero values?? This is my code for drawing a doughnut pie chart:
const renderPortfolioSectorPie = (sectors, intl) => {
if (sectors.length > 0) {
const sectorsName = sectors
.map(sector => sector.name);
const sectorsValue = sectors
.map(sector => sector.subtotal);
const sectorsPercentage = sectors
.map(sector => sector.percentage);
const customeSectorsPercentage = sectorsPercentage.map(h =>
`(${h})`
);
let sectorsCounter = 0;
for (let i = 0; i < sectorsName.length; i += 1) {
if (sectorsName[i] !== sectorsName[i + 1]) {
sectorsCounter += 1;
}
}
const sectorsData = {
datasets: [{
data: sectorsValue,
backgroundColor: [
'#129CFF',
'#0c6db3',
'#4682B4',
'#00FFFF',
'#0099FF',
'#3E3BF5',
'#3366CC',
'#3399FF',
'#6600FF',
'#3366CC',
'#0099CC',
'#336699',
'#3333FF',
'#2178BA',
'#1F7AB8',
'#1C7DB5'
],
hoverBackgroundColor: [
'#129cff',
'#0c6db3',
'#4682B4',
'#00FFFF',
'#0099FF',
'#3E3BF5',
'#3366CC',
'#3399FF',
'#3366CC',
'#0099CC',
'#336699',
'#3333FF',
'#2178BA',
'#1F7AB8',
'#1C7DB5'
],
titles: sectorsName,
labels: sectorsValue,
afterLabels: customeSectorsPercentage,
}]
};
return (
<Doughnut
data={sectorsData}
width={250}
height={250}
redraw
options={{
legend: {
display: false
},
maintainAspectRatio: true,
responsive: true,
cutoutPercentage: 80,
animation: {
animateRotate: false,
animateScale: false
},
elements: {
center: {
textNumber: `${sectorsCounter}`,
text: intl.formatMessage({ id: 'pie.sectors' }),
fontColor: '#4a4a4a',
fontFamily: "'EurobankSans'",
fontStyle: 'normal',
minFontSize: 25,
maxFontSize: 25,
}
},
/*eslint-disable */
tooltips: {
custom: (tooltip) => {
tooltip.titleFontFamily = 'Helvetica';
tooltip.titleFontColor = 'rgb(0,255,255)';
},
/* eslint-enable */
callbacks: {
title: (tooltipItem, data) => {
const titles = data.datasets[tooltipItem[0]
.datasetIndex].titles[tooltipItem[0].index];
return (
titles
);
},
label: (tooltipItem, data) => {
const labels = data.datasets[tooltipItem.datasetIndex]
.labels[tooltipItem.index];
return (
labels
);
},
afterLabel: (tooltipItem, data) => {
const afterLabels = data.datasets[tooltipItem.datasetIndex]
.afterLabels[tooltipItem.index];
return (
afterLabels
);
},
},
},
}}
/>
);
}
I wanted to do the same thing, but I could not find a way to do it. So, that is what I found as a workaround:
After getting the data, you update your options:
this.setState({
doughnutOptions: {
tooltips: {
callbacks: {
label: function () {
let value = response.data.total;
let label = response.data.name;
return value === 0 ? label : label + ': ' + value;
}
}
}
}
});
My Doughnut looks like that:
<Doughnut data={this.state.myData} min-width={200} width={400}
height={400} options={this.state.doughnutOptions}/>
And initially, the doughnutOpitions are just one empty object defined in the state:
doughnutOptions: {}
That is how it will look when no data:
If you have found a better way of showing no data, please share. If not, I hope that workaround would be good enough for you!

Categories