since 2 hours I'm trying a simple thing: displaying data from database with Chart.js. I've checked like 4 tutorials, viewed 3 SO-Threads, but nothing is working as intented to. Don't know if its just a minor problem or what the problem is...
So what I'm trying is the following:
stats.php:
<script>
function getRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
</script>
<script>
$(document).ready(function(){
$.ajax({
url: "stats_api.php",
method: "GET",
success: function(data) {
console.log(data);
var chart = new Chart(document.getElementById("pie-chart"), {
type: 'pie',
data: {
labels: data,
datasets: [{
label: "Anzahl Asservate",
backgroundColor: [getRandomColor(),getRandomColor(),getRandomColor(),getRandomColor(),getRandomColor(),getRandomColor(),getRandomColor(),getRandomColor(),getRandomColor(),getRandomColor()],
data: [1,2,3,4,5,6,7,8,9,10],
}]
},
options: {
title: {
display: true,
text: 'Kategorien-Verteilung der Asservate'
}
}
});
}
});
});
</script>
stats_api.php:
<?php
require 'databaseConnection.php';
$datumStart = "2010-12-19 08:38:32";
$datumEnde = "2019-12-19 08:38:32";
$v_rp_ass_kat = $database->query("
select s.* from (select #DatumStart:='$datumStart',#DatumEnde:='$datumEnde') parm , v_rp_ass_kat s;")->fetchAll();
$labels = [];
foreach($v_rp_ass_kat as $element){
array_push($labels, $element[2]);
}
echo json_encode($labels);
The json_encode is returning this:
["Mobiltelefon","Smartphone","SIM-Karte","Tablet","Navigationsger\u00e4t","USB-Stick","Speicherkarte","PC","Notebook","Festplatte"]
With that, I'm getting the error saying data.labels.map is not a function.
I also tried it without the foreach in php, instead a json_encode of $v_rp_ass_kat and then do a
labels = [];
for(var i in data){
labels.push(data[i].kategorie);
}
But this somehow splits the array into single letters, so instead of 10 labels with one word each, I get like 100 labels, one for every letter of the json array...
What do I do wrong?
I reckon, you're getting the response as a string and passing it to the labels property, while it expects an array of strings. (same mistake in your fiddle as well)
To convert that response string to an array, you can use JSON.parse()
...
data: {
labels: JSON.parse(data),
...
also, you should use the chart.js version 2.x, as you're using it's syntax.
Working fiddle - https://jsfiddle.net/bf4v9272/5/
https://www.dyclassroom.com/chartjs/chartjs-how-to-draw-bar-graph-using-data-from-mysql-table-and-php
$(document).ready(function(){
$.ajax({
url: "http://localhost/chartjs/data.php",
method: "GET",
success: function(data) {
console.log(data);
var player = [];
var score = [];
for(var i in data) {
player.push("Player " + data[i].playerid);
score.push(data[i].score);
}
var chartdata = {
labels: player,
datasets : [
{
label: 'Player Score',
backgroundColor: 'rgba(200, 200, 200, 0.75)',
borderColor: 'rgba(200, 200, 200, 0.75)',
hoverBackgroundColor: 'rgba(200, 200, 200, 1)',
hoverBorderColor: 'rgba(200, 200, 200, 1)',
data: score
}
]
};
var ctx = $("#mycanvas");
var barGraph = new Chart(ctx, {
type: 'bar',
data: chartdata
});
},
error: function(data) {
console.log(data);
}
});
});
i hope you will Get
Related
I am trying to draw a two-line chart with two datasets that share the same labels using chart.js on my ASP.NET MVC app.
I am only getting the data from "Value" plotted on the chart and not "Age" and I cannot find the reason why.
Relevant Controller code:
public ActionResult GetLineChartData()
{
List <LineChartData> dataForLineChart = new List <LineChartData> ();
dataForLineChart.Add(new LineChartData {
Date = DateTime.NOW, Value = 100, Age = 20
});
return Json(dataForLineChart, JsonRequestBehavior.AllowGet);
}
Relevant View code:
$.ajax({
type: "Post",
url: '#Url.Action("GetLineChartData", "Posts")',
contentType: false,
processData: false,
data: dataFromForm,
dataType: "json",
traditional: true,
success: function (data) {
console.log(data);
var labels = data.map(function (e) {
return e.Date;
});
var data = data.map(function (e) {
return e.Value;
});
var data2 = data.map(function (e) {
return e.Age;
});
var ctx = scatterChart.getContext('2d');
var config = {
type: 'line',
data: {
labels: labels,
datasets: [{
label: "Test"
data: data,
backgroundColor: 'rgba(0, 119, 204, 0.3)'
},
{
label: "Test",
data: data2,
backgroundColor: 'rgba(242, 204, 143, 1)'
}
]
}
};
}
});
(Some code I do not consider important is hidden)
Issue & Concern
Because the below line overwrites the original data value.
var data = data.map(function (e) {
return e.Value;
});
After the above line, now the data array was overwritten as an array of integers instead of an array of objects. Based on your sample response from API, the current value of data will be: [100].
var data2 = data.map(function (e) {
return e.Age;
});
From the above line, it can't find the Age property in the element. Hence the result of data2 will be: [undefined].
This is why the data2 is not rendered in the chart.
Solution
Create another variable for the data transformation to avoid overwriting the existing data value.
var dataset = data.map(function (e) {
return e.Value;
});
var dataset2 = data.map(function (e) {
return e.Age;
});
var config = {
type: 'line',
data: {
labels: labels,
datasets: [
{
label: 'Test',
data: dataset,
backgroundColor: 'rgba(0, 119, 204, 0.3)',
},
{
label: 'Test',
data: dataset2,
backgroundColor: 'rgba(242, 204, 143, 1)',
},
],
},
};
Demo # StackBlitz
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
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;
}
// 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,
}]
}
});
i am working on showing data in a bar chart with chart.js . my json response is already ready there but chart says its undefined values.
here is jquery with json
$(document).ready(function(){
$.ajax({
url: "<?php base_url();?>/charts/getsome",
method: "GET",
success: function(data) {
console.log(data);
var month = [];
var customers = [];
for(var i in data) {
month.push("Customer in" + data[i].apply_month);
customers.push(data[i].no_customers);
}
var chartdata = {
labels: month,
datasets : [
{
label: 'monthly customers',
backgroundColor: 'rgba(200, 200, 200, 0.75)',
borderColor: 'rgba(200, 200, 200, 0.75)',
hoverBackgroundColor: 'rgba(200, 200, 200, 1)',
hoverBorderColor: 'rgba(200, 200, 200, 1)',
data: customers
}
]
};
// alert(chartdata);
var ctx = $("#mycanvas");
var barGraph = new Chart(ctx, {
type: 'bar',
data: chartdata
});
},
error: function(data) {
console.log(data);
}
});
});
below is a snap for json response in console
And here is also a snap for chart with error
Please guide me where i am wrong. Thanks
You are getting response as a string. you should parse using JSON.parse(data)
success: function(data) {
console.log(data);
data = JSON.parse(data)
//the rest of your code
}