Charts.js rendering issue on page load - javascript

I have a strange issue occurring with my Charts.js line chart.
Upon page load, nothing seems to be visible in the <canvas> element:
However, once you resize the browser window, the chart displays as intended:
Has anyone else encountered this issue and know of a way to fix it?
The JavaScript for my chart is below. Please let me know if I need to alter it in any way to fix this issue.
function drawLineChart() {
var dates = [];
var clientCosts = [];
$.ajax({
url: '../inc/wip-data.php',
dataType: 'json'
}).done(function(data) {
data.forEach(function(item) {
dates.push(item.date);
clientCosts.push(item.clientCostsTotal);
});
});
console.log(dates, clientCosts);
var chartData = {
labels: dates,
datasets: [{
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointHighlightStroke: "rgba(151,187,205,1)",
data: clientCosts
}]
};
// Get the context of the canvas element we want to select
var ctx = document.getElementById("myChart").getContext("2d");
// Instantiate a new chart
var myChart = new Chart(ctx, {
responsive: true,
type: 'line',
data: chartData,
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
}
drawLineChart();
This issue is not replicating in JS Bin. The only difference between the JS Bin and my local build is the AJAX call for the data, so that leads me to believe the AJAX call is what is causing the issue. Any guidance on what may be calling this issue would be appreciated.

The data used by the chart is not available when the chart is created. This is because the ajax call is asynch, and the data becomes available only when the ajax request is complete.
In order to have the chart visible right away, you will need to use this call myChart.update(), in the "done" function of the ajax call after you populate the data, in order to update the chart:
...
data.forEach(function(item) {
dates.push(item.date);
clientCosts.push(item.clientCostsTotal);
});
myChart.update();

Related

Chart.js showing different graphs with select

basically, I have made a Graph that looks like this Image.
I want to make the Graph update whenever I choose an option ( a location in this example). Any idea how could I go on about this?
It sounds like you need to update the chart data whenever the user selects a value from the dropdown. So, add an event listener to the location selector dropdown element, then replace the chart data with the data for the selected location, then call chart update. That part is very simple. It's explained in the chart.js docs under Updating Charts. https://www.chartjs.org/docs/latest/developers/updates.html
For example, if you had location data in an object and a transformData function to convert it to x/y coordinates, you might do something like this for a line chart:
const defaultLocation = 'munchen';
const chart = new Chart(chartCanvas,
{
type: 'line',
data: transformData(locationData[defaultLocation]),
options: {
animation: false,
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
},
x: {
type: 'timeseries',
},
},
},
});
const locationSelector = document.getElementById("location-selector");
locationSelector.addEventListener('change', ({ target }) => {
chart.data = transformData(locationData[target.value]);
chart.update();
});

Can't pass data to chart.js graph

I’m trying to pass my data to the graph but it won't work. If I add numbers to it manually like
data: [1,2,3]
Than it works. In my code you'll see that I console.logged my data.weight and data.goal. They appear in the console as they should.
Here's the code:
var endpoint = '/api/data';
var defaultDataW = [];
var defaultDataG = [];
$.ajax({
method: 'GET',
url: endpoint,
success: function(data){
console.log(data.weight);
console.log(data.goal);
defaultDataW = data.weight;
defaultDataG = data.goal;
var graph = document.getElementById("weight-graph");
Chart.defaults.global.defaultFontFamily = "Lato";
Chart.defaults.global.defaultFontSize = 18;
var dataFirst = {
label: "Your Weight (Kg)",
data: defaultDataW,
lineTension: 0,
fill: false,
borderColor: 'red'
};
var dataSecond = {
label: "Your Goal (Kg)",
data: defaultDataG,
lineTension: 0,
fill: false,
borderColor: 'blue'
};
var DateData = {
labels: [], //Dates will be here
datasets: [dataFirst, dataSecond]
};
var chartOptions = {
legend: {
display: true,
position: 'top',
labels: {
boxWidth: 80,
fontColor: 'black'
}
}
};
var lineChart = new Chart(graph, {
type: 'line',
data: DateData,
options: chartOptions
});
},
error: function(error_data){
console.log("Error");
console.log(error_data);
}
})
})
You are doing most everything right, but you are changing 'type' of the data.....
what you are doing RIGHT
var defaultDataW = [];
This sets the data to an ARRAY.
Though, in the ajax, you are doing this:
defaultDataW = data.weight;
Which, by your other comments, clearly says that 'data.weight' is an INTEGER.
So, when you try to use that (now INTEGER) as data in a Chart
data: defaultDataW,
It doesn't work (and, no surprise......)
Chart.js requires an ARRAY (at minimum) to work - https://www.chartjs.org/docs/master/general/data-structures/
Now, how can you fix this?????
Pretty simple......
In your ajax, change
defaultDataW = data.weight;
To ADD to the ARRAY (instead of replacing the array with an integer....)
defaultDataW.push(data.weight);
In case you add other code later (or for future projects, putting things in a function, etc....), you might want to also learn about a way to CLEAR that array. It doesn't hurt to do it now, though the way your code is it really should not be needed. I'm including it here for others to reference, etc.
Before doing a 'push' (certainly if you are doing a loop, etc.), you may need to clear the array first, like this:
defaultDataW.length = 0;
This will empty the array and then you can 'push' what you really want in there. If the array is not empty and you push, then you will have the old data as well as the new (of course, depending on what you are doing, that may be a good thing - though in this case, it is not)

Use variable as data in apexcharts

I'm trying to display a chart in apexcharts, and use a variable as the data. When I do this, nothing is displayed. See the following:
var message = '[1,4]'
var options = {
chart: {
type: 'line',
sparkline: {
enabled: true,
}
},
series: [{
data: message,
}],
}
var chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();
Using the variable message as data doesn't work. When I switch the line:
data: message,
to
data: [1,4]
it displays correctly. However, I must use a variable. How do I do this?
You declared message variable as STRING, It is expecting an ARRAY
Please change
var message = '[1,4]'
to
var message = [1,4];

HighChart Line Graph not Showing

I am using data from a csv file to generate a line graph using Highchart. Here is my code:
/* Define Initial and basic Options */
var options = {
chart: {
type: 'line',
renderTo: 'graph_container'
},
title: {
text: 'FanniemaeAcquisition Cash Flow'
},
yAxis: {
title: {
text: 'Amount($)'
}
},
series: []
};
/* Parse CSV File */
$.get('{% static "data/FanniemaeAcquisitions.csv" %}', function(csv) {
var lines = csv.split('\n');
var series = {
name: '',
data: []
};
$.each(lines, function (lineNo, line) {
var items = line.split(',');
$.each(items, function (itemNo, item) {
if(itemNo == 1){
if (lineNo == 0){
series.name = item;
} else {
series.data.push(parseFloat(item));
}
}
});
});
options.series.push(series);
console.log(options.series);
});
// Create the chart
var chart = new Highcharts.Chart(options);
However this isn't working. I tried testing it by manually inputting data like so:
series: [{
name: 'Installation',
data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175]
},
and that works fine. So I took a look at the variables being passed to series. The one that works(manual input):
The one that doesn't work(From CSV):
Any ideas?
EDIT: Okay. something weird is going on here. Highchart isn't showing on the webpage but it showing when I download as PNG. The weirder part is that it shows on the webpage if I MANUALLY add in number values but when I extract the values form CSV the graph disappears... But when I download as PNG it shows the graph...Any ideas??
SECOND EDIT: Okay, so when I do: console.log(JSON.stringify(options.series[0].data));
nothing shows up. This would mean that the values parsed from the csv file appear after the graph is generated. So how do I fix this? lol
The problem was due to Javascript's Asynchronous Issues. I simply wrapped my function in a $.when and it worked!

Javascript Unresponsive Script Error

I am trying to get data to load on my chart from an API. All the data is getting to the chart correctly, but the chart doesn't load and I get the unresponsive script error. I'm using Highcharts. Any suggestions? Thanks. My code is below.
Model
public function ajax_get_chart() {
$quotes = $this->rest->get('api/1/BTCUSD/trades/fetch');
$series_data = array();
$results = $quotes->return;
$i = 0;
foreach ($results as $quote)
{
$series_tmp = array(
'date' => $quote->date,
'price' => $quote->price
);
$series_data[]= $series_tmp;
$i= $i+1;
}
die (json_encode($series_data));
return TRUE;
}
Javascript
$(document).ready(function() {
var chart;
$.ajax({
url: "/chart/ajax_get_chart", // the URL of the controller action method
dataType: "json",
success: function(result)
{
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
defaultSeriesType: 'bar'
},
title: {
text: 'Stacked bar chart'
},
xAxis: {
title: {
text: 'Price'
}
},
yAxis: {
min: 0,
title: {
text: 'Date'
}
},
legend: {
backgroundColor: '#FFFFFF',
reversed: true
},
tooltip: {
formatter: function() {
return ''+
this.series.name +': '+ this.y +'';
}
},
plotOptions: {},
series: result
});
}
});
});
Sounds like the problem is that there's too much data to present.
You can try using a speedier browser (Chrome usually works pretty fast), limiting the data, or trying another charting library.
Limiting the data is probably the most likely one to work. If you need to show all the data, the best way to go about it would be to only load partial data and then if the user for example scrolls the chart, load the missing data.
Another way to present more data at the same time would be to calculate averages for the data on server. For example, if the ticker data is from every second, you could pre-calculate hourly or even daily averages on the server. This generally allows you to show a relatively accurate chart without causing performance problems, and many libraries also support dynamically loading more accurate data if you zoom the chart.
Highcharts can not handle so huge number of data, but using Highstock with dataGrouping or lazy-loading you should be able to handle a lot of points, see demo.
Also this article should help.

Categories

Resources