Use data from database in Chart.js/Rails - javascript

I want to show a line chart on my "Weights" index page with Chart.js in my Rails app (a weight loss app). I have a table that holds a user's weight (as "kilograms") for each day (as "day"). I am able to show a line chart, however, but only with static data - not with the data from my Weights table.
What I want to do now is to have "day" on the x-axis and "kilograms" on the y-axis.
How can I achieve this? And as I just started coding few months ago: how should the code look like?
Thx a lot.
This is the code from my weights index.html.erb:
<canvas id="myChart" width="400" height="200"></canvas>
<script>
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["day 1", "day 2", "day 3", "day 4", "day 5", "day 6"],
datasets: [{
label: 'My Weight',
data: [82.4, 79.6, 79.3, 78.4, 77.5, 75.1],
backgroundColor: [
'rgba(0, 0, 0, 0.1)',
],
borderColor: [
'rgba(0,0,0,0.9)',
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:false
}
}]
}
}
});
</script>

The main thing that had me stuck forever was that Chart.js relies on calling its tooltiptemplate with <% however this would then be interpreted by ERB and cause a problem. The workaround is adding another % which tells erb not to interpret the tags it otherwise would have. That's not very well documented but what are you going to do. As for the rest, in your view-page.html.erb file you want to add the chart scripts at the bottom:
Set your timeline X-Axis (I'll show you how to load it dynamically but this could be static if you want in which case just enter them directly into the timeline array):
<script type="text/javascript">
$(function() {
var lineData = {
<% timeline = []
datapoints = []
#workout.each do |workout|
timeline << workout.day
datapoints << workout.weight
end
%>
//The "raw" method is needed to stop the auto escaping of the output. Test this out in your console and you will notice the output is formatted like "[\"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\"]" This escaping of quotes causes errors in js...
labels: <%= raw timeline.to_json %>,
datasets: [{
label: "Weight Gain/Loss",
fillColor: "rgba(26,179,148,0.5)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#127A65",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: <%= raw datapoints.to_json %>,
}]
};
If you want to set some options remember to use the <%% tag for tooltips!
var lineOptions = {
scaleOverride : true,
tooltipTemplate: "<%%if (label){%>(<%%=label%>) <%%}%><%%= value %> pounds",
};
//NOTE THE ABOVE TOOLTIP REQUIRES A SECOND % SIGN ON OPENING TAGS SO THAT IS IS TAKEN LITERALLY AND NOT INTERPRETED BY RAILS ERB!!!!!!!!
var ctx = document.getElementById("myChart").getContext("2d");
var myNewChart = new Chart(ctx).Line(lineData, lineOptions);
});
</script>

I, too, was struggling with getting this to work on Rails, but I discovered that I did not have to use the Rails template escape characters that chart.js says that you do. In my case (needing to show a zero in the label when the value is set to 0.1), this is what I did:
tooltipTemplate: function(context){
var labelVal = (context.value == '0.1')? '0' : context.value;
var newLabel = context.label + ': ' + labelVal;
return newLabel;
}

Related

Setting Canvas Limits Over the Existing Dataset Values

I've got a little problem with html5 canvas. I've got a couple of line charts made but they have a problem with maximum grid values (sort of field limits inside the canvas itself). The chart is building from a dataset coming from the database and only through these values.
The example: sample chart
As you can see here, the above limit is 5.55, and the question is how to change that to a bigger value (for example, using a percentage of such maximum value or something so that other charts' offsets would match as well)?
The code:
$('#graf_' + i + '').html('<canvas id="lineChart' + i + '" width="' + $(".graf").width() + '" height="200"></canvas>');
var lineData = {
labels: data["headers"],
datasets: [{
label: data["rates"][i]["VltName"],
fillColor: "transparent",
strokeColor: data["rates"][i]["VltColor"],
pointColor: data["rates"][i]["VltColor"],
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: getRatesArr
}]
};
var lineOptions = {
scaleShowGridLines: true,
scaleGridLineColor: "rgba(0,0,0,.05)",
scaleGridLineWidth: 1,
bezierCurve: false,
pointDot: true,
pointDotRadius: 4,
pointDotStrokeWidth: 1,
pointHitDetectionRadius: 20,
datasetStroke: true,
datasetStrokeWidth: 2,
datasetFill: true
};
var ctx = document.getElementById("lineChart" + i).getContext("2d");
var myNewChart = new Chart(ctx).Line(lineData, lineOptions);
Hope my explanation is not too vague. Thanks in advance!
If you update to the latest Chart.js version (currently v2.6.0), you can use the max tick configuration option to set the max number to display on the axis:
options: {
scales: {
yAxes: [{
ticks: {
max: yourMaxNum
}
}]
}
}
If you want to set yourMaxNum to the largest number in all your dataset arrays, simply use the JavaScript Math.max() method to determine this number, and set the above chart config option to this number when you create all your line charts.
The Chart.js documentation lists additional tick configuration options that you might also find useful.

Rendering Rails json data in chartjs

I have my canvas tag in my portfolio#show page:
<%= content_tag :canvas, "", id: "positions_chart", width: "300", height: "300", data: {positions: #positions } %>
In my portfolio.js file I have created a chartInstance object:
$(document).ready(function () {
var context = document.getElementById('positions_chart');
var ctx = context.getContext("2d");
var pieData = {
labels: $("#positions_chart").data(positions['name']),
datasets: [
{
backgroundColor: "rgba(220,220,220,1)",
borderColor: "rgba(220,220,220,1)",
data: $("#positions_chart").data(positions['quantity'])
}
]
}
var chartInstance = new Chart(ctx, {
type: 'pie',
data: pieData,
options: {
responsive: true
}
});
console.log(chartInstance);
});
I'm loading the data I want in the DOM -- a collection of position data.
<canvas id="positions_chart" width="600" height="600"
data-positions="[{"id":1,"ticker":"AAPL","name":"Apple Inc.",
"quantity":20,"portfolio_id":1,"created_at":"2016-10-22T18:19:36.255Z",
"updated_at":"2016-10-23T01:21:38.731Z","price":"116.6"},...
style="width: 300px; height: 300px;"></canvas>
The examples I've seen online are how to handle preloaded data within the data and dataset attributes in the js file. I want to have a pie chart with labels corresponding to the ticker names and using data from my rails database. I grab the data in the canvas tag and have access to it in my js file.
From what I understand, I'm passing the pieData object to the ctx object and whichever graph I chose (in this case pie) it should render the label and dataset to a graph. I'm not sure why the pie chart isn't showing up.
Is this what you want?
You can pass data you get from rails database and insert it into your js code immediately (no need to put it to data attribute in canvas tag).
I see you are using chart js v2 so no need to get context I think.
Also I fixed your code a little bit.
in your js code
$(document).ready(function() {
var positionsQuantity = <%= raw(#positions.map(&:quantity)) %>;
var positionName = <%= raw(#positions.map(&:name)) %>;
var ctx = $('#positions_chart');
var pieData = {
labels: positionName,
datasets: [
{
label: "pie labels",
data: positionsQuantity,
backgroundColor: "rgba(220,220,220,1)",
borderColor: "rgba(220,220,220,1)"
}]
}
var chartInstance = new Chart(ctx, {
type: 'pie',
data: pieData,
options: {
responsive: true
}
});
});
Hope it works!

chart.js Hide empty Chart and keep previous data if no data? .net MVC

I have a chart where based on date, data changes. Problem current date is default and sometimes there is no data to show. is it possible with chart.js to check for if there is data in current chart and keep previous if there is none. Subing it with DIV placeholder ect. Same data is also in DataTable. Not really good at writing conditions yet.
Things I tried so far:
if (sampleTable != null && sampleTable.rows.count > 0) {
$("#labelDiv").hide();
}
if (parsedData.Item2 = null)
{
$("#labelDiv").hide();
}
if (buyerData == null) {
$("#labelDiv").hide();
}
chart
var buyerData = {
labels: parsedData.Item2,
datasets: [
{
label: "Lazi Chart",
fillColor: "rgba(10,190,10,0.6)",
strokeColor: "rgba(151,187,205,0.8)",
highlightFill: "rgba(151,187,205,0.75)",
highlightStroke: "rgba(151,187,205,1)",
data: parsedData.Item3,
}
]
}
barChartOptions.datasetFill = false;
barChart.Bar(barChartData, barChartOptions);
I figured it out. I check if object is empty and then if it is place a div saying experimental data and fake chart. Tnx for Any Help.
if (parsedData.Item1 != "") {
$("#labelDiv").hide();
$("#buyers").show();
}
else {
$("#labelDiv").show();
$("#FakeData").show();
$("#buyers").hide();
var barData = {
labels: ['SaaS', 'Virtual Machines', 'Networking', 'Storage', 'Data Managment'],
datasets: [
{
label: '2010 customers #',
fillColor: '#382765',
data: [2500, 1902, 1041, 610, 1245]
},
{
label: '2014 customers #',
fillColor: '#7BC225',
data: [3104, 1689, 1318, 589, 1199]
}
]
};
var context = document.getElementById('FakeData').getContext('2d');
var clientsChart = new Chart(context).Bar(barData);
I don't know chart.js, but by it's name I'll assume it's a plugin to draw graphs.
Probably, it'll require that you feed them with data, or at least, with an endpoint where read the data, so it can draw a graph that represent these data.
Now... if you have a data collection, or an endpoint where check for data, won't be easy to check these data and redirect your code execution than try to do that from within a plugin?
If the collection of data is empty or you don't get data from the endpoint just end the execution or return it to the last call (which you could have stored previously if necessary)

Chart.js custom tooltipTemplate index

I have this chart made with Chart.js.
var data = {
labels: ["", "", "", "2015-08-28", "2015-08-29", "2015-08-30", "2015-08-31", ],
websites: ["", "", "", "gamesoutletCrawler", "gamesoutletCrawler", "G2PLAY", "instantgaming", ],
datasets: [{
label: "Best price last 7 days",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [0, 0, 0, 34.5, 36.8, 37.3, 37.99, ]
}]
};
window.onload = function() {
var ctx = document.getElementById("chartkeys").getContext("2d");
window.myLine = new Chart(ctx).Line(data, {
responsive: true,
tooltipTemplate: "<%= data.websites[idx] %>",
scaleLabel: "<%= Number(value).toFixed(2).replace('.', ',') + ' €'%>"
});
}
On my tooltip template, I want to use values from data.websites but I don't know how to pass in the index for my tooltip array. This is not working:
<%= data.websites[idx] %>
idx is wrong, it's not the index the system is using. Any idea what I have to write here to show the index tooltip when you hover on the graph?
If I write <%= data.websites %>, it's showing me all the websites in the array, not the one hovered.
You can use a function instead of a template string
...
tooltipTemplate: function (d) {
return data.websites[data.labels.indexOf(d.label)]
},
...
Note that this requires the labels to be unique, or if there are duplicate labels that it not matter which one is active (for instance, in your data, the first 3 labels are the same but that won't cause any problems because the first 3 entries in the websites array too are the same. If they were different this method will not work)

Chart.js - Where to put global chart configuration?

I am trying to set up a Chart.js line graph with the following code. Where in this do I place the Chart.defaults.global = {} or Chart.defaults.global.responsive = true; code?
Chart.js docs can be found here: http://www.chartjs.org/docs/
<!-- Chart.js -->
<script src="http://cdnjs.cloudflare.com/ajax/libs/Chart.js/0.2.0/Chart.min.js"></script>
<script>
var ctx = document.getElementById("myChart").getContext("2d");
var data = {
labels: ["Week 1", "Week 2", "Week 3", "Week 4", "Week 5", "Week 6", "Week 7"],
datasets: [
{
label: "My Second dataset",
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(151,187,205,1)",
data: [86, 74, 68, 49, 42]
}
]
};
var options = {
...
};
var myLineChart = new Chart(ctx).Line(data, options);
</script>
There are two ways to accomplish what you're looking for. This way
var myLineChart = new Chart(ctx).Line(data, options);
var options = Chart.defaults.global = {
responsive: true,
maintainAspectRatio: true
};
or, this way
var myLineChart = new Chart(ctx).Line(data, {
responsive: true,
maintainAspectRatio: true
});
However, to make it responsive you'll have to add some extra CSS
canvas{
width: 100% !important;
height: auto !important;
}
so there's no need for inline CSS
Working demo
In accordance with the comment of #JustinXL below and the latest version of Chart.js there's no need for extra CSS, so check out the updated version.
Updated demo
You could set the options of your chart, but you can also set the global (as you asked) to avoid setting this specific property for each chart you want to instantiate.
You just have to set
Chart.defaults.global.elements.responsive = true;
before instantiating the chart, in your case, before
var myLineChart = new Chart(ctx).Line(data, options);
(P.S.: Chartjs V2)

Categories

Resources