hide labels and 0 values in chart.js? - javascript

I am beginner on this Chart.js and wanna ask, How can I hide the labels and 0 values in the bar Chart. I cannot just hide the whole Dataset since I am using a SQL Table to get the Values "into" Chart.Js. I just want the bar chart show only if the labels have the value. Need your help
sample chart
{
{
$.post("datachartasr.php",
function (data)
{
console.log(data);
var intake = [];
var active = [];
var inactive = [];
var deffered = [];
var widthdrawn = [];
var dis_ter_dereg = [];
var missing = [];
for (var i in data) {
intake.push(data[i].intake);
active.push(data[i].active);
inactive.push(data[i].inactive);
deffered.push(data[i].deffered);
widthdrawn.push(data[i].widthdrawn);
dis_ter_dereg.push(data[i].dis_ter_dereg);
missing.push(data[i].missing);
}
var chartdata = {
labels: intake,
datasets: [
{
label: 'Active Status',
backgroundColor: '#1E90FF',
borderColor: '#1E90FF',
hoverBackgroundColor: '#1E90FF',
hoverBorderColor: '#666666',
data: active
},
{
label: 'Deferred Status',
backgroundColor: '#708090',
borderColor: '#708090',
hoverBackgroundColor: '#708090',
hoverBorderColor: '#666666',
data: deffered
},
.....
.....
.....
]
};
var graphTarget = $("#graphCanvas");
var barGraph = new Chart(graphTarget, {
type: 'bar',
data: chartdata,
});
});
}
}

You can have the below function inside data labels to hide the Zero value:
options: {
plugins: {
datalabels: {
display: function(context) {
return context.dataset.data[context.dataIndex] !== 0; // or >= 1 or ...
}
}
}
}
See more on this issue here https://github.com/chartjs/chartjs-plugin-datalabels/issues/6

Related

Is there a better way to create an 'n' number of charts in ChartJS and ASP.NET C#?

EDIT: I have narrowed it down to something like this:
for (i = 0; i < data.length; i++) {
const newCanvas = document.createElement("canvas");
newCanvas.id = data[i].design_name;
const currentDiv = document.getElementById("chartSpace");
var parentDiv = document.getElementById("gridHere");
parentDiv.insertBefore(newCanvas, currentDiv);
createChart([data[i].design_name], [data[i].design_start, data[i].design_end]);
}
With the create chart making the chart id = to the array 'labels':
const myChart = new Chart(
document.getElementById(labels),
config
);
I am attempting to create a tool that creates an 'n' number of charts in ChartJS and save each of them as images. Currently, designButtonClick() sends the 'event_fky' value to
getDesigns(event_fky) in my controller. This method returns all designs with that foreign key. In turn, the chart plots each design on the chart. I need to evolve this into
something that can make a group individual charts for each design based on how many designs there are. My current solution, still conceptual, is to have methods in my controller
create chart variables 'chartData [data here]' and 'labels[datahere]' while looping through the designs returned from getDesigns, and sending those back to the JS script createChart
'n' number of times for each design. It would also send html chart/html element ids based on the design_name attribute to send back to createChart. This way, it is create a unique
chart 'n' number of times.
To save the charts as images, I would use the same set of element ids generated by getDesigns to send the charts to images using JS' toBase64Image() function and saving them to the
user's system.
Is this the best way of solving this problem? Or is this spaghetti, and is there a better method for this? My attempts to find better online answers have only resulted in docs on
updating one chart dynamically, not creating a dynamic number of charts. Much help is appreciated, code is below as well as a screenshot of the current chart output.
JavaScript:
var labels = [];
var cData = [];
function designButtonClick() {
var event_fky = 3;
$.ajax({
url: 'Tree/getDesigns',
type: 'POST',
data: { event_fky }
}).done(function (data) {
for (i = 0; i < data.length; i++) {
labels.push(data[i].design_name);
cData.push([data[i].design_start, data[i].design_end])
}
createChart(labels, cData);
});
}
function createChart(labels, cData) {
const data = {
labels: labels,
datasets: [{
barThickness: 2,
categoryPercentage: .5,
label: 'Design Time',
data: cData,
backgroundColor: [
'rgba(255, 26, 104, 0.2)'
],
borderColor: [
'rgba(255, 26, 104, 1)'
],
borderWidth: 1,
borderSkipped: false,
borderRadius: 20
}]
};
const config = {
type: 'bar',
data,
options: {
indexAxis: 'y',
scales: {
y: {
beginAtZero: true
},
x: {
min: 0,
max: 6000,
ticks: {
stepSize: 1000
}
}
}
}
};
const myChart = new Chart(
document.getElementById('myChart'),
config
);
}
C# Controller:
public ActionResult getDesigns(int? event_fky)
{
var designs = from e in _context.designs
where (event_fky.HasValue ? e.event_fky == event_fky : e.event_fky == null)
select new
{
design_pky = e.design_pky,
design_name = e.design_name,
design_start = e.design_start,
design_end = e.design_end
};
return this.Json(designs, JsonRequestBehavior.AllowGet);
}
Designs Table:
--------Design--------
design_pky |int
event_fky |int
design_name |varchar
design_start |number
design_end |number
Screenshot of Chart
This is a working answer for the javascript:
var eventList = function () {
var tmp = null;
$.ajax({
'async': false,
url: 'Tree/getEventIDs',
type: 'POST',
data: {},
'success': function (data) {
tmp = data;
}
});
return tmp;
}();
for (var i = 0; i < eventList.length; i++) {
event_fky = eventList[i].event_pky;
event_name = eventList[i].event_name;
event_length = eventList[i].event_end;
var designList = function () {
var tmpi = null;
$.ajax({
'async': false,
url: 'Tree/getDesigns',
type: 'POST',
data: {event_fky},
'success': function (data1) {
tmpi = data1;
}
});
console.log(event_fky);
console.log(tmpi);
return tmpi;
}();
var dLabels = [];
var dLengths = [];
for (var j = 0; j < designList.length; j++) {
dLabels.push(designList[j].design_name);
dLengths.push([designList[j].design_start, designList[j].design_end]);
}
const newCanvas = document.createElement("canvas");
newCanvas.id = event_name;
const currentDiv = document.getElementById("chartSpace");
var parentDiv = document.getElementById("gridHere");
parentDiv.insertBefore(newCanvas, currentDiv);
if (dLabels.length != 0) {
createChart(dLabels, dLengths, event_name, event_length);
}
}
}
function createChart(labels, cData, evName, evLen) {
// setup
const data = {
labels: labels,
datasets: [{
barThickness: 4,
categoryPercentage: .5,
label: evName,
data: cData,
backgroundColor: [
'rgba(' + Math.random() * 85 + ', ' + Math.random() * 170 + ', ' + Math.random() * 255 + ', 1)'
],
borderColor: [
'rgba(255, 26, 104, 1)'
],
borderWidth: 0,
borderSkipped: false,
borderRadius: 20
}]
};
// config
const config = {
type: 'bar',
data,
options: {
indexAxis: 'y',
scales: {
y: {
beginAtZero: true
},
x: {
min: 0,
max: evLen,
ticks: {
stepSize: 100
}
}
}
}
};
// render init block
const myChart = new Chart(
document.getElementById(evName),
config
);
return myChart;
}

Risers or bars of Dynamically built ChartJs from json not aligning to bottom of y axis

I have strange behaviour from bars or risers in a dynamically built Chartjs chart.
They don't begin at point 0 on the y-axis and not all of them show.
I have tried a variety of ways as found here or other forums, but no success.
Please help.
The code to build it is from json ex ajax to MVC Controller/Action.
chartSetup.jsonDataSets = new List<ChartDataset>();
ChartDataset jsonDataSets = new ChartDataset
{
data = "[408, 547, 675, 534]",
label = "Actual",
backgroundColor = "#8e5ea2"
};
chartSetup.jsonDataSets.Add(jsonDataSets);
jsonDataSets = new ChartDataset
{
data= "[350, 447, 725, 534]",
label = "Budgeted",
backgroundColor = "red"
};
chartSetup.jsonDataSets.Add(jsonDataSets);
If I hardcode particularly the datasets, for the chart, then no problem.
var type = 'bar';
var xLabels = ["May", "Jun", "Jul", "Aug", "Sept"];
var topTitle = { display: true, text: 'Maintenance Costs', fontStyle: 'bold', fontSize: 18, fontColor: 'white' };
var canvasTyreCostsChart = $("#canvasMaintenanceBar").get(0).getContext("2d");
var datasources = [
{
label: "Budgeted",
backgroundColor: 'red',
data: [133, 221, 783, 1078]
},
{
label: "Actual",
backgroundColor: "#8e5ea2",
data: [408, 547, 675, 734]
}
];
var regionalCountCostBar = new Chart(canvasTyreCostsChart,
{
type: type,
data: {
labels: xLabels,
datasets: datasources,
},
options:
{
responsive: true,
title: topTitle,
legend: { position: 'bottom' },
}
});
But done dynamically the bars float above the zero point on the y axis.
Here's the code.
datasources = jsonData['jsonDataSets'];
var dynamicChartCanvas = $("#canvas-" + columnID).get(0).getContext("2d");
var xLabelsArr = [];
$.each(xLabels, function (key, val)
{
var rec = xLabels[key];
xLabelsArr.push(rec['label']);
});
var label;
var backgroundColor;
var data2 = "";
var data3 = [];
var DS = [];
var dataSource2;
// Extract the individual elements
$.each(datasources, function (key, val)
{
var rec = datasources[key];
$.each(rec, function (key, val)
{
if (key == "label")
{
label = val;
}
if (key == "backgroundColor")
{
backgroundColor = val;
}
if (key == "data")
{
data2 = rec[key];
var xx = data2.replace("[", "").replace("]","").split(",");
data3.push(xx);
}
});
dataSource2 =
{
label: label,
backgroundColor: backgroundColor,
data: data3,
}
console.log("ds label " + JSON.stringify(label));
console.log("data3 " + JSON.stringify(data3));
data3 = [];
DS.push(dataSource2);
});
console.log("DS " + JSON.stringify(DS));
var tempData2 = {
labels: xLabelsArr,
datasets: DS,
};
var topTitle = { display: true, text: 'Maintenance Costs', fontStyle: 'bold', fontSize: 18, fontColor: 'white' };
var chart = new Chart(dynamicChartCanvas,
{
type: type,
data: tempData2,
options:
{
responsive: responsive,
title: topTitle,
legend: { position: 'bottom' },
}
});
The object array as logged:
DS [{"label":"Actual","backgroundColor":"#8e5ea2","data":[["408"," 547"," 675"," 534"]]},{"label":"Budgeted","backgroundColor":"red","data":[["350"," 447"," 725"," 534"]]}]
What was required, was a further iteration thru the JSON array in the data object, getting each value and building it into a js array.
if (key == "data")
{
var dataRec = rec[key];
var jsonData = JSON.parse(dataRec);
xValuesArray = [];
for (var i = 0; i < jsonData.length; i++)
{
var value = jsonData[i];
xValuesArray.push(value);
}
}
});
chartDataset =
{
label: label,
backgroundColor: backgroundColor,
data: xValuesArray,
}
chartDatasets.push(chartDataset);

attempting to destroy previous graph on canvas

I am creating multiple graphs on the same canvas but I am unable to successfully use the destroy() API to clean up the previous data.
HERE IS MY JS CODE FOR CREATING A CHART
const getCountryDataByMonth = async (country) => {
document.getElementById('casesGraphHeader').innerHTML = "Loading....";
const response = await fetch ('https://cors-anywhere.herokuapp.com/https://pomber.github.io/covid19/timeseries.json');
const data = await response.json();
const reports = await data[country];
var i;
var dateList = [];
var caseByDay = [];
var deathsByDay = [];
for(i = 0; i < reports.length; i++){
dateList.push(reports[i].date);
caseByDay.push(reports[i].confirmed);
deathsByDay.push(reports[i].deaths);
}
//GRAPH FOR TOTAL CASES
var casesOptions = {
type: 'bar',
data: {
labels: dateList,
datasets: [
{
label: 'Total Cases',
data: caseByDay,
backgroundColor: '#f49d12',
borderColor: '#f49d12',
fill: false,
borderWidth: 2
}
]
},
options: {
legend: {
labels: {
fontSize: 15
}
},
scales: {
yAxes: [{
ticks: {
reverse: false,
fontSize: 15
}
}],
xAxes: [{
ticks: {
fontSize: 15
}
}],
}
}
}
var totalCasesChart = document.getElementById('totalCasesContainer').getContext('2d');
new Chart(totalCasesChart, casesOptions);
document.getElementById('casesGraphHeader').innerHTML = "Total Cases for "+country;
//GRAPH FOR TOTAL Deaths
var deathOptions = {
type: 'bar',
data: {
labels: dateList,
datasets: [
{
label: 'Total Deaths',
data: deathsByDay,
backgroundColor: '#e84c3d',
borderColor: '#e84c3d',
fill: false,
borderWidth: 2
}
]
},
options: {
legend: {
labels: {
fontSize: 15
}
},
scales: {
yAxes: [{
ticks: {
reverse: false,
fontSize: 15
}
}],
xAxes: [{
ticks: {
fontSize: 15
}
}],
}
}
}
var totalCasesChart = document.getElementById('totalDeathsContainer').getContext('2d');
new Chart(totalDeathsContainer, deathOptions);
document.getElementById('deathsGraphHeader').innerHTML = "Total Deaths for "+country;
};
function renderChart(){
getCountryDataByMonth(document.getElementById('myInput').value);
}
function defaultChart() {
getCountryDataByMonth('US');
}
window.onload = defaultChart;
This is what I tried. I basically did
if(caseBar){
caseBar.destroy();
}
However, this does not work. In my FIDDLE you can try to type China first click to create the graph and then type Italy. Then HOVER over the Italy graph and you will see the stats from china appear on the graph.
Your code is riddle with issues, here is some of the stuff I see:
Look at what you are doing when you create the new charts:
var totalCasesChart = document.getElementById('totalCasesContainer').getContext('2d');
var caseBar = new Chart(totalCasesChart, casesOptions);
document.getElementById('casesGraphHeader').innerHTML = "Total Cases for " + country;
vs
var totalCasesChart = document.getElementById('totalDeathsContainer').getContext('2d');
new Chart(totalDeathsContainer, deathOptions);
document.getElementById('deathsGraphHeader').innerHTML = "Total Deaths for " + country;
You are calling the:
await fetch('https://cors-anywhere.herokuapp.com/https://pomber.github.io/...');
again and again when you should do it just once...
There are many variables that should be global to reduce what you do in getCountryDataByMonth, a perfect example are the totalCasesChart and caseBar
I made a few tweaks to your code here:
https://raw.githack.com/heldersepu/hs-scripts/master/HTML/chart_test.html

How can I highlight a particular datapoint in chartjs, where my data is coming from json array?

// here I am taking another json encoded data from phpfile
$(document).ready(function () {
showGraph();
});
function showGraph()
{
{
$.post("phpfile.php",
function (data)
{
console.log(data);
var name = [];
var marks = [];
var height=[];
//and here as I couldn't encode two json array's separetly I'm declaring it to a variable and then using it
var jsonfile =[{"height":"85","st_name":"Name1"},{"height":"100","st_name":"Name3"},{"height":"92","st_name":"Name4"},{"height":"104","st_name":"Name5"},{"height":"91","st_name":"Name2"},{"height":"99","st_name":"Name6"},{"height":"140","st_name":"AI346"},{"height":"139","st_name":"abc"},{"height":"141","st_name":"def"},{"height":"140","st_name":"ghi"},{"height":"144","st_name":"jkl"},{"height":"130","st_name":"lmn"},{"height":"142","st_name":"opq"},{"height":"132","st_name":"rst"},{"height":"135","st_name":"xyz"},{"height":"135","st_name":"asdfsf"}];
//here I am reading the data from phpfile(1st Json array)
for (var i in data) {
name.push(data[i].st_name);
marks.push(data[i].height);
}
//here i am trying to access data from second json
for (var i=0;i<jsonfile.length;i++){
if(jsonfile[i].height==100)
{ height.push(jsonfile[i].height)}
}
//my graph function ,when I do this I am getting a single point with second json(height variable) but I need to highlight the particular point under a condition... I am not understanding how to do it.
var chartdata = {
labels: name,
datasets: [
{
label: 'height',
fill:false,
lineTension:0.5,
backgroundColor: '#5B2C6F',
borderColor: '#5B2C6F',
pointHoverBackgroundColor: '#5B2C6F',
pointHoverBorderColor: '#5B2C6F',
data: marks
//data:height
},
{
label: 'weight',
fill:false,
lineTension:0.1,
backgroundColor: '#C0392B',
borderColor: '#C0392B',
pointHoverBackgroundColor: '#C0392B',
pointHoverBorderColor: '#C0392B',
data:height,
//data:height
}
]
};
var graphTarget = $("#graphCanvas");
var lineGraph = new Chart(graphTarget, {
type: 'line',
data: chartdata,
options :{
scales:{
xAxes: [{
display: false //this will remove all the x-axis grid lines
}]
}
}
});
});
}
}
</script>
i will try to improve this.
var data =[{"height":"85","st_name":"Name1","color":"rgba(85, 85, 255, 255)"},{"height":"100","st_name":"Name3","color":"rgba(255, 0, 0, 2)"},{"height":"92","st_name":"Name4","color":"rgba(85, 85, 255, 255)"},{"height":"104","st_name":"Name5","color":"rgba(85, 85, 255, 255)"}];
var height = [];
var label = [];
var color = [];
for(i = 0; i<data.length; i++){
height.push(data[i]['height']);
label.push(data[i]['st_name']);
color.push(data[i]['color']);
}
var ctx = document.getElementById('myLine').getContext('2d');
var myLineChart = new Chart(ctx, {
type: 'line',
data: {
labels: label,
datasets: [{
data: height,
pointBorderColor: color,
}]
}
});

Chart.js not showing data until I click on the label 3 times

I'm adding a chart in a website and I'm having a weird issue with chart.js. I'm loading the data from 2 arrays that are created when the page is loaded from a json file.
The issue is that the data it's not showing until I click on the label of the chart 2 times. At load, there is no info, 1st click x labels are showing up and in 2nd click both, x labels and data are showing up. After that, clicking on the label of the dataset work as expected.
I assumed my problem was that I was loading the data before the chart exists, so, my idea was to encapsulate everything in a function and call it when clicking a button that shows the chart, but it's keeping doing the same thing. How would you fix it?
Here is my html related code:
<div class="popup">
<span class="popuptrend" id="myPopup"><canvas id="myChart" width="auto" height="400"></canvas></span>
</div>
And my JS code:
$(function(){
$("#showTrend").click(function(){
createChart();
var popup = document.getElementById("myPopup");
popup.classList.toggle("show");
});
});
function createChart(){
var labels = [];
var dataValue = [];
$.getJSON("./resources/chart.json", function(jsonData) {
var index = 0;
for (var key in jsonData) {
if(index == 0){ // SKIP FISRT ITEM
index++;
}else{
labels.push(key);
dataValue.push(parseFloat(jsonData[key]));
}
}
});
var dataVar = {
labels: labels,
datasets:
[{
label: "Value",
backgoundColor: 'rgba(255, 0, 0, 0.2)',
borderColor: 'rgba(255, 0, 0, 0.8)',
borderWith: 1,
data: dataValue
}]
};
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: dataVar,
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
}
And a extract from my data json file:
{
"15/04/2017":"67.34375",
"16/04/2017":"67.3203125",
}
And a gif of the behaviour.
Thanks!
Since $.getJSON() method is asynchronous, you should construct your chart inside it­'s callback function, like so :
...
$.getJSON("./resources/chart.json", function(jsonData) {
var index = 0;
for (var key in jsonData) {
if (index == 0) { // SKIP FISRT ITEM
index++;
} else {
labels.push(key);
dataValue.push(parseFloat(jsonData[key]));
}
}
var dataVar = {
labels: labels,
datasets: [{
label: "Value",
backgoundColor: 'rgba(255, 0, 0, 0.2)',
borderColor: 'rgba(255, 0, 0, 0.8)',
borderWith: 1,
data: dataValue
}]
};
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: dataVar,
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
});
...
Hopefully, this will solve your problem.
As I posted before as a comment, try doing like this:
$.getJSON(...).done(var dataVar....)

Categories