How do I implement Laravel Analytics with Chart.js - javascript

Hi guys I am busy building a dashboard for my website and I want to add a chart that shows the sessions for the last 7 days. I have already setup my service account and I am receiving the data. Here is the output I receive:
[
{"date":{"date":"2016-08-22 15:38:36.000000","timezone_type":3,"timezone":"UTC"},"visitors":"0","pageViews":"0"},
{"date":{"date":"2016-08-23 15:38:36.000000","timezone_type":3,"timezone":"UTC"},"visitors":"0","pageViews":"0"},
{"date":{"date":"2016-08-24 15:38:36.000000","timezone_type":3,"timezone":"UTC"},"visitors":"0","pageViews":"0"},
{"date":{"date":"2016-08-25 15:38:36.000000","timezone_type":3,"timezone":"UTC"},"visitors":"0","pageViews":"0"},
{"date":{"date":"2016-08-26 15:38:36.000000","timezone_type":3,"timezone":"UTC"},"visitors":"0","pageViews":"0"},
{"date":{"date":"2016-08-27 15:38:36.000000","timezone_type":3,"timezone":"UTC"},"visitors":"0","pageViews":"0"},
{"date":{"date":"2016-08-28 15:38:36.000000","timezone_type":3,"timezone":"UTC"},"visitors":"0","pageViews":"0"},
{"date":{"date":"2016-08-29 15:38:36.000000","timezone_type":3,"timezone":"UTC"},"visitors":"1","pageViews":"5"}
]
My Controller function is like this:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use LaravelAnalytics;
class AdminController extends Controller
{
public function index(){
$analytics = LaravelAnalytics::getVisitorsAndPageViews(7);
return view('admin.index')
->with(json_encode($analytics));
}
}
I forgot to mention that I am using the Spatie\Laravel-Analytics library.
My Javascript looks like this to render a demo chart.
var ctx = document.getElementById("sessions");
var sessions = new Chart(ctx, {
type: 'line',
data: {
labels: ["Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
datasets: [{
label: 'Sessions Last 7 Days',
data: [4,8, 19, 3, 5, 4, 3],
backgroundColor: [
'rgba(52, 73, 94,0.2)'
],
borderColor: [
'rgba(52, 73, 94,1)'
],
borderWidth: 1
}]
},
options: {
responsive: true,
legend: {
display: false
},
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
My question is how do I get the data received from json to display in the chart?

if you already have a json object/file you can get the data with json.parse(json var) , it will return you the data

You take 7 from your controller but the output is 8, check that also. And In your JS
var myData = [
#foreach($analytics as $analis)
{{ $analis->visitors }}, //remeber to put comma (,) at end for array
#endforeach
]
data: {
datasets: [{
data: myData,
}]
},

Related

Chartjs using array in label field

I am making a simple bar chart using Chartjs 3.x
I make requests to a server to fetch json data and then store certain parts of it into arrays, here is the code for this:
serverData = JSON.parse(http.responseText);
console.log(serverData);
stundenProjekt = serverData.abzurechnen.nachProjekt.map((s) => {
return s.second.summe;
});
labelsP = serverData.abzurechnen.nachProjekt.map((p) => {
return p.first;
});
I then want to use these arrays in the data and label fields of the chart. I'm using stundenProjekt as data and it works fine, but when I use labelsP as label for the chart, it doesn't work. Here is the code of the chart:
const data = {
labels: labelsP,
datasets: [{
label: 'Projekte',
data: stundenProjekt,
backgroundColor: [
'#f4f40b',
],
borderColor: [
'#B1B101',
],
borderWidth: 3,
}]
};
if (barChartProjekt) {
data.datasets.forEach((ds, i) => {
barChartProjekt.data.datasets[i].data = ds.data;
barChartProjekt.labels = newLabelsArray;
})
barChartProjekt.update();
} else {
barChartProjekt = new Chart(chart, {
type: 'bar',
data: data,
options: {
responsive: true,
plugins: {
legend: {
labels: {
color: "white",
font: {
size: 18
}
}
}
},
scales: {
y: {
ticks: {
color: "white",
font: {
size: 18,
},
stepSize: 1,
beginAtZero: true
}
},
x: {
ticks: {
color: "white",
font: {
size: 14
},
stepSize: 1,
beginAtZero: true
}
}
}
}
});
}
The only workaround I have found is to copy the contents of labelsP and paste them in the label field. These are the contents of labelsP and how I did the workaround:
["nexnet-SB-Cloud", "AUTEC - PSK-System²", "Fritzsche", "nexnet-eBalance", "IfT - Neuentwicklung", "wattform", "Migration", "Fahrwerkregelkreis", "bmp greengas", "nexnet-SQL-Abfragen über API", "lambda9", "Nord Stadtwerke", "edifact", "SOLVIT", "BürgerGrünStrom", "SOLVCPM", "lambda captis", "SOLVEDI", "green city power", "max.power"]
const data = {
labels: ["nexnet-SB-Cloud", "AUTEC - PSK-System²", "Fritzsche", "nexnet-eBalance", "IfT - Neuentwicklung", "wattform", "Migration", "bmp greengas", "Fahrwerkregelkreis", "nexnet-SQL-Abfragen über API", "lambda9", "Nord Stadtwerke", "edifact", "SOLVIT", "BürgerGrünStrom", "SOLVCPM", "lambda captis", "SOLVEDI", "green city power", "max.power"],
datasets: [{
label: 'Projekte',
data: stundenProjekt,
backgroundColor: [
'#f4f40b',
],
borderColor: [
'#B1B101',
],
borderWidth: 3,
}]
};
In this way, the chart works and everything shows up as it should, however, I want to use it as shown in the first snippet of code, as labelsP gets updated every some seconds with new data extracted from the server. So, why is it that if I put labelsP alone in the label field it doesn't work, but if I copy and paste the contents of labelsP in the label field, it does work?
The problem is that you add the labels to the wrong position in the chart configuration.
Instead of...
barChartProjekt.labels = newLabelsArray;
try this...
barChartProjekt.data.labels = newLabelsArray;

Highcharts update x-axis categories dynamically

i'm looking for help with updating the x-axis categories on a Highcharts chart with periodically received data.
The chart is defined in a file called forecastgraph.html. It is loaded to index.php, the webpage where I want it displayed, by means of <?php require("widget/forecastgraph.html"); ?>. The chart renders as expected.
Live data which is handled via a js script (called mqtt.js) that receives incoming mqtt data in json format and using jquery updates various parts of index.php in this way: $("#elementid").html(a.b.c);. I load mqtt.js in the head of index.php using <script src="./js/mqtt.js"></script> This again works flawlessly.
What I am struggling with is how to pass incoming data from mqtt.js to the chart to update it as new data comes in. Specifically, I am trying to update the xAxis categories and the corresponding value pairs. Periodically, mqtt.js receives a new weather forecast and so the xAxis categories need to be updated with the new time period that the forecast applies to and the data needs to be updated to reflect the new high and low temperatures for the respective forecast periods.
The code for the chart is posted below. Any help would be appreciated.
Baobab
<script type="text/javascript">
$(function () {
$('#forecastgraph').highcharts({
chart: {
type: 'columnrange',
backgroundColor: 'rgba(0,0,0,0)',
borderWidth: 0,
margin: [12, 6, 36, 20]
},
title: {
text: null,
},
exporting: {
enabled: false
},
credits: {
enabled: false
},
xAxis: {
categories: [1,2,3,4],
labels: {
y: 30,
style: {
color: 'white',
fontSize: '10px',
fontWeight: 'bold'
}
}
},
yAxis: {
title: {
enabled: false,
x: -14,
},
labels: {
align: 'left'
},
maxPadding: 0.5,
plotLines: [{
value: 10, //normmax
width: 2,
color: '#FF0000'
},{
value: 2, //normmin
width: 2,
color: '#009ACD'
}]
},
tooltip: {
enabled: false
},
plotOptions: {
columnrange: {
dataLabels: {
enabled: true,
style: {
textOutline: 'none'
},
crop: false,
overflow: 'none',
formatter: function () {
var color = this.y === this.point.high ? '#33C4FF' : 'red';
return '<span style="font-size: 12px; font-family:helvetica; font-weight:normal; text-shadow: none; color:' + color + '">' + this.y + '°</span>';
}
}
}
},
legend: {
enabled: false
},
series: [{
name: 'Temperatures',
data: [
[20, -3],
[5, -2],
[6, -2],
[8, -15]
],
color: '#b9deea',
borderColor: '#92cbde',
borderRadius: 4
}]
});
});
</script>
EDIT: Additional Information.
The incoming json data looks like this:
[{
"period": "Monday",
"condition": "Cloudy",
"high_temperature": "7",
"low_temperature": "-2"
"icon_code": "10",
"precip_probability": "20"
}, {
"period": "Tuesday",
"condition": "A mix of sun and cloud",
"high_temperature": "6",
"low_temperature": "-2"
"icon_code": "02",
"precip_probability": "20"
}, {
"period": "Wednesday",
"condition": "A mix of sun and cloud",
"high_temperature": "3",
"low_temperature": "-5"
"icon_code": "02",
"precip_probability": "20"
}, {
"period": "Thursday",
"condition": "A mix of sun and cloud",
"high_temperature": "1",
"low_temperature": "-10"
"icon_code": "02",
"precip_probability": "20"
}]
The function responsible for the incoming json formatted data in the mqtt.js script loaded to index.php handles the incoming data in this way (mqtt.js is started when index.php is loaded):
function onMessageArrived(message) {
console.log("onMessageArrived: " + message.payloadString);
//Env Canada forecast
if (message.destinationName == "myHome/ec/json_data_ec") {
var data = JSON.parse(message.payloadString);
$("#forecast_period_1").html(data[0].period); // update div forecast_period_1 in index.php for debugging purposes and show that data is coming in
forecast_period_1 = (data[0].period); // assign to global var
forecast_period_1_high = (data[0].high_temperature); // global var
forecast_period_1_low = (data[0].low_temperature); // global var
Updating various html elements throughout index.php with the incoming data works great and is stable. What I have attempted to do, but with no success, is to update the chart using the data placed in the global variables (declared as global at he beginning of the script) by the mqtt.js script. In the example above, forecast_period_1 needs to be used as the first of the four xAxis categories and forecast_period_1_high and forecast_period_1_low, to update the respective hi and lo values in the chart's data.
Is this an output that you want to achieve? In the below demo, I wrote a function that takes a high and low temperatures value and next is triggered on the button. The new data is attached to the chart via using the series.update feature.
Demo: https://jsfiddle.net/BlackLabel/he768cz3/
API: https://api.highcharts.com/class-reference/Highcharts.Series#update
I have found a solution for it. First, you have to store the chart in a variable then after you are able to update chart data. Like below
var chart = $('#forecastgraph').highcharts({ ...option })
Update xAxis or series data
// Update xAxis data label
chart.update({
xAxis: {
categories: [1,2,3,4]
}
});
// Update series data
chart.series[0].update({
data: [
[20, -3],
[5, -2],
[6, -2],
[8, -15]
]
});

Chart js not display graph

I use chart js to display my graph, but it wont displaying it...
I try to check it in jsfiddle and it works there, but on my website it actually wont work.
The source from chart.js is correctly embedded, so i don't know what the error could be
jsfiddle Link
My code:
var diemeltalsperrectx = document.getElementById('diemeltalsperre').getContext('2d');
var diemeltalsperre = new Chart(diemeltalsperrectx, {
type: 'line',
data: {
labels: [
'08.05.2020 - 18:15:00',
'09.05.2020 - 01:00:00',
'09.05.2020 - 06:15:00',
'09.05.2020 - 18:15:00',
'10.05.2020 - 01:00:00',
'10.05.2020 - 06:15:00',
],
datasets: [{
fill: true,
label: 'Pegelstand (cm)',
data: [
374.91,
374.9,
374.9,
374.87,
374.87,
374.84,
],
backgroundColor: [
'rgba(0,0,128, 1)'
],
borderColor: [
'rgba(0,0,128, 1)'
],
borderWidth: 3
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.js"></script>
<canvas id='diemeltalsperre' width='800' height='400'></canvas>
The values ​​are very close to each other, try with:
beginAtZero:false

Changing chart data dynamically with C# from SQL database

This is my chart code.
<!-- Graphs -->
<script src="../Scripts/Chart.min.js"></script>
<script>
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
datasets: [{
data: [1, 6, 2, 5, 9, 5, 6],
label: "Issues Resolved",
lineTension: 0,
backgroundColor: 'transparent',
borderColor: '#007bff',
borderWidth: 4,
pointBackgroundColor: '#007bff'
}, {
data: [8, 5, 8, 6, 0, 2, 2],
label: "Issues Raised",
lineTension: 0,
backgroundColor: 'transparent',
borderColor: '#ff8400',
borderWidth: 4,
pointBackgroundColor: '#ff8400'
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: false
}
}]
},
legend: {
display: true
},
title: {
display: true,
text: 'Issues Raised VS Issues Resolved'
}
}
});
</script>
This graph, though working fine, is static. What I want to ask is whether I can dynamically change the data (of which I'll always have 7 values, for each day of the week) in my datasets (of which I'll always have 2 values, for issues raised and issues resolved) from my .aspx.cs (which will get this data from my SQL Database) at runtime. And if so, how?
Thank you for your help.
I had a similar issue and found this solution. This solution requires you to use using System.Web.Services; and I will leave it to you to implement access to your SQL Database. But hopefully this solution can help you too!
Try using the following in the .ASPX file:
<!-- Graphs -->
<script src="../Scripts/Chart.min.js"></script>
<script>
$(function () {
$.ajax({
type: 'POST',
dataType: 'json',
contentType: 'application/json',
url: 'BackendFileName.aspx/GetChartData', // change to your .aspx filename
data: '{}',
success: function (response) {
drawChart(response.d);
},
error: function () {
console.error("Error loading data! Please try again.");
}
});
})
function drawChart(dataValues) {
var issuesResolved = [];
var issuesRaised = [];
for (var i = 0; i < dataValues.length; i++) {
issuesResolved[i] = dataValues[i].issuesResolved;
issuesRaised[i] = dataValues[i].issuesRaised;
}
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
datasets: [{
data: issuesResolved,
label: "Issues Resolved",
lineTension: 0,
backgroundColor: 'transparent',
borderColor: '#007bff',
borderWidth: 4,
pointBackgroundColor: '#007bff'
}, {
data: issuesRaised,
label: "Issues Raised",
lineTension: 0,
backgroundColor: 'transparent',
borderColor: '#ff8400',
borderWidth: 4,
pointBackgroundColor: '#ff8400'
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: false
}
}]
},
legend: {
display: true
},
title: {
display: true,
text: 'Issues Raised VS Issues Resolved'
}
}
});
}
</script>
Then add the following methods within backend file:
// Arbitrary class to hold required data from SQL Database
public class ChartDetails
{
public string IssuesResolved { get; set; }
public string IssuesRaised { get; set; }
public ChartDetails()
{
}
}
// Method that will be called by JQuery script
[WebMethod]
public static List<ChartDetails> GetChartData()
{
List<ChartDetails> dataList = new List<ChartDetails>();
// Access SQL Database Data
// Assign SQL Data to List<ChartDetails> dataList
return dataList;
}
You most certainly can. Take a look at the documentation here, you just need to implement the AJAX polling to see if the source dataset has changed.
I believe what you can do is:
Create a class level string variable in your code behind for holding the serialized array like
protected string weeklyData;
In Page_Load eventhandler, fetch the data from SQL database and populate an array of numbers int or decimal or floats depending upon your stored data. Lets say you end up with an array containing data
int[] data = [8, 5, 8, 6, 0, 2, 2];
Use the JavaScriptSerializer class to serialize it into a string and assign to weeklyData class variable like this:
JavaScriptSerializer serializer = new JavaScriptSerializer();
weeklyData = serializer.Serialize(data);
Assign weeklyData variable in your chart initialization code like:
data: <%= weeklyData %>,
enter code here
Another better option will be to write a WEB API service which will expose an endpoint for fetching the weekly data in json array format. Then, you can use jquery get method to get data and then initialize chart
$.get('{enpointurl}', function(weeklyData) {
//Write chart initialization code here and pass weekly data to chart data option
});
Add a hidden field:
<asp:HiddenField ID="hdnLabels" runat="server" Value="" />
<asp:HiddenField ID="hdnData" runat="server" Value="" />
In your chart script add:
labels: [<%= hdnLabels.Value %>],
datasets: [
{
data: [ <%= hdnData.Value %>],
... other options here,
}
]
In code behind:
public void ShowChartData()
string _data = "";
string _labels = "";
......Loop your SqlDataReader
....
....
while (dr.Read())
{
_labels = _data + dr["DayOfWeek"].ToString() + #",";
_data = _data + dr["DayOfWeekValue"].ToString() + #",";
}
_labels = _label.Remove(_label.Length - 1);
_data = _data.Remove(_data.Length - 1);
hdnLabels.Value = _labels;
hdnData.Value = _data;
}
Hope this helps...

Show No data message when chart has no data

I am trying to show no data message when chart has no data.
Is it correct?
var ctx = document.getElementById('mycanvas').getContext('2d');
var chart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ["aa", "bb", "cc", "dd"],
datasets: [{
label: "My First dataset",
backgroundColor: ['red', 'blue', 'green', 'yello'],
data: data.length ? data: [{ label: "No Data", value: 100 }],
}]
},
options: {
legend: {
position: 'right',
labels: {
boxWidth: 12
}
},
tooltips: { bodyFontSize: 12 }
}
});
I am not getting No data message when data length is 0.
Easiest is to use conditional rendering.
Assuming you're using AngularJS (you referenced tag), you can use ngIf directive. If data array is empty, then don't display chart.
<canvas id="myChart" ng-if="data != 0"></canvas>
<span ng-if="data == 0">No data</span>
Else, you can solve it in your script, by checking before or after draw the data length. I recommend you this snippet.
Other solution following your wish could be to adapt drawn data to received data.
if($scope.requestedLeaveTypeCount.length > 0){
data = {
labels: ["EL", "AL", "PL", "CL"],
datasets: [{
label: "My First dataset",
backgroundColor: ['#F0CB8C', '#A9D5D4', '#E8A3D7', '#CFA3FD'],
data: $scope.requestedLeaveTypeCount,
}]
}
} else {
data = {
labels: ["No data"],
datasets: [{
labels:'No data',
backgroundColor: ['#D3D3D3'],
data: [100]
}]
}
}
https://plnkr.co/edit/QXljAeeM4Ul3Y47EPcbq?p=preview

Categories

Resources