I'm developing part of application in which i need to generate reports on some user athletes and preview on chart following:
dates and number of exposures to certain lift
Here is the html and javascript:
<div class="chart" id="bar-chart-#exposureReport.AthleteId" style="height: 300px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">
<script>
drawChart('#exposureReport.CoachId', '#exposureReport.AthleteId');
function drawChart(coachId, athleteId) {
//debugger;
$.getJSON('#Url.Action("FetchAthleteChartData", "Reports")?coachId=' + coachId + '&athleteId=' + athleteId,
function (data) {
var datax = JSON.stringify(data);
alert(datax);
Morris.Bar({
element: 'bar-chart-' + athleteId,
resize: true,
barSizeRatio: 0.12,
barGap: 3,
data: $.parseJSON(datax),
barColors: ['#ff0000'],
xkey: ['exposures'],
ykeys: ['dates'],
labels: ['Times exposed'],
hideHover: 'auto'
});
}
);
}
</script>
</div>
I foreach all the reports i have on current view and preview them. I want to show a chart for each report.
I call the javascript function and pass the coachId and athleteId values and let server fetch the data for me:
[HttpGet]
public JsonResult FetchAthleteChartData(string coachId, string athleteId)
{
var exerciseReport =
_applicationUserOperations.GetAllExposureReportsForCoachByAthleteId(coachId, athleteId);
var filteredDates = exerciseReport.Exposures.Select(x => x.ExposureDate).ToList();
var filteredExposures = exerciseReport.Exposures.Select(x => x.NumberOfLifts).ToList();
var result = new
{
Dates = filteredDates,
Exposures = filteredExposures
};
return Json(result);
}
When my alert(datax) triggers it shows (I have only one training/exercise/lift entry atm):
{"dates":["2018-06-01T00:00:00"],"exposures":[5]}
Is this correct format to parse ? How do I parse it so the chart data can understand it and display it.
Related
I am a beginner when it comes to the following technologies:
- ASP.NET MVC
- Entity Framework
- JavaScript (in this instance, CanvasJS)
I am trying to render a chart based on a Data Model that I have created in my solution. I am following the tutorial here (adapted to my own purposes) https://canvasjs.com/docs/charts/integration/asp-net-mvc-charts/how-to/asp-net-mvc-charts-data-entity-database/ and I have completed the following.
Created a Model of my data via EF
Passed that data from my Controller to my View
Attempted to render the chart in the View CSHTML
However, the chart does not render. When I use Chrome Debugging, the Javascript shows that the 'result' is my strongly typed model, but this must be incorrect as the error is Uncaught SyntaxError: Unexpected end of input
The rendered Javascript is as follows:
<h2>StoreView - Testing this for store group P777S001</h2>
<hr />
<div class="container-fluid">
<div class="row">
<div class="col-md-6">
<div class="text-info">Here are some examples of sales data via Entity Framework</div>
</div>
<div class="col-md-6">
<div id="chartContainer"></div>
</div>
</div>
</div>
<script type="text/javascript">
var result = System.Collections.Generic.List`1[InSiteDashboard.Models.InSiteStoreSalesSummaryTable];
var datapoints = [];
for (var i = 0; i < result.length; i++) {
datapoints.push({ label: result[i].x, y: result[i].y });
}
$(function () {
var chart = new CanvasJS.Chart("chartContainer", {
theme: "light2",
zoomEnabled: true,
animationEnabled: true,
title: { text: "Line chart" },
data: [{
type: "line",
dataPoints: dataPoints,
}]
});
chart.render();
});
</script>
I am passing this to the View using the following code (it's prototyping so the code is messy apologies)
Controller:
string _servername = $"P{store}S001";
var sales = insite.InSiteStoreSalesSummaryTables.Where(s => s.ServerName == _servername && s.daily_sales_figure > 0);
//var storeEntries = db.StoreSystemInformations.Where(s => s.StoreNumber == store);
if (sales == null)
{
return HttpNotFound();
}
ViewBag.TestValue = $"Testing this for store group {_servername}";
return View(sales.ToList());
Can anyone see something I'm obviously doing wrong here?
From first glance, I assumed your problem seem occurred because of this line:
var result = System.Collections.Generic.List`1[InSiteDashboard.Models.InSiteStoreSalesSummaryTable];
I think you're passing list directly to a JS definition intended to create JS array, but Razor returns fully-qualified name of the List<InSiteDashboard.Models.InSiteStoreSalesSummaryTable> collection because Razor implicitly called ToString() in the view instead of iterating it.
Since List``1[InSiteDashboard.Models.InSiteStoreSalesSummaryTable] is not recognized as a JS identifier or property, then "Unexpected end of input" message was thrown because of invalid syntax.
You could use model serialization to pass List<T> collection as JS array, as in example below (assumed you have model directive with #model IEnumerable<InSiteStoreSalesSummaryTable> or #model List<InSiteStoreSalesSummaryTable> as implied by return View(sales.ToList())):
// standard way
var result = JSON.parse('#Html.Raw(Json.Encode(Model))');
// using Newtonsoft.Json library
var result = JSON.parse('#Html.Raw(JsonConvert.SerializeObject(Model))');
Here is an example implementation of the script:
#model IEnumerable<InSiteStoreSalesSummaryTable>
<!-- other HTML elements, skipped for brevity -->
<script>
var result = JSON.parse('#Html.Raw(Json.Encode(Model))');
var datapoints = [];
for (var i = 0; i < result.length; i++) {
datapoints.push({ label: result[i].x, y: result[i].y });
}
$(function () {
var chart = new CanvasJS.Chart("chartContainer", {
theme: "light2",
zoomEnabled: true,
animationEnabled: true,
title: { text: "Line chart" },
data: [{
type: "line",
dataPoints: dataPoints,
}]
});
chart.render();
});
</script>
I want to display the club name and the number of children from the table below in a piechart
Here is the behind code for the PieChart webform I have created:
public partial class PieChart : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
string club_name;
int no_children;
public int TargetClub_No()
{
string CS = ConfigurationManager.ConnectionStrings["dbyouthworkConnectionString"].ConnectionString;
using (MySqlConnection con = new MySqlConnection(CS))
{
MySqlCommand cmd = new MySqlCommand("SELECT no_children, club_name FROM pie_chart WHERE club_name = 'Target Club'", con);
con.Open();
MySqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
club_name = rdr["club_name"].ToString();
no_children = Convert.ToInt32(rdr["no_children"]);
}
return no_children;
}
}
}
I have already downloaded the js.chart file and jquery file
Here is the code in the PieChart.aspx file I have created :
<body>
<form id="form1" runat="server">
<canvas id="mycanvas" width="256" height="256"></canvas>
<script>
$(document).ready(function () {
var ctx = $("#mycanvas").get(0).getContext("2d");
// pie chart data
var t = <% TargetClub_No(); %>;
var data = [
{
value: t,
color: "cornflowerblue",
highlight: "lightskyblue",
label: "Target Club"
},
{
value: 50,
color: "lightgreen",
highlight: "yellowgreen",
label: "Lightgreen"
},
{
value: 40,
color: "orange",
highlight: "darkorange",
label: "Orange"
}
];
//draw
var piechart = new Chart(ctx).Pie(data);
});
</script>
<div>
</div>
</form>
*Here I have firstly tried to input the number of children from target club however when I run the code I get a blank page instead of a pie chart
SCREEN SHOTS USING DEV TOOLS IN CHROME:
This one shows that I have done something wrong in calling 'public int TargetClub_No()'
Here is the screen shot of the networks tab:
Not sure what this tab means though...
First there are syntax errors in your JS..
This portion:
var t = '<% TargetClub_No(); %>'
//var data = [
should look like this:
var t = <%= TargetClub_No() %>;
var data = [
Now your C# method TargetClub_No() needs to return a value to assign to t.
For what you are trying to do at first you want to return the number of children from target club. Like this:
public int TargetClub_No()
{
...
//nothing else needs to change
...
return no_children;
}
Eventually you will probably want your method TargetClub_No() to return all of the data in a way that you can assign it to data directly.
Here is an article that does exactly what you want (and a little more):
Chart.js Asp.net : Create Pie chart with database jQuery Ajax C#
i have this code and i want to change the static data with data from csv
the csv is look like:
GPA,Total Distance,id
3.27,22.0,20032202
2,64.0,20038107
2.81,10.0,20051566
2.33,66.5,20060382
i want to add the GPA in y axis
and total distance in the X axis
when i try to add code from d3 library it does not works
<html>
<head>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {
packages: ['corechart', 'line']
});
google.charts.setOnLoadCallback(drawBasic);
function drawBasic() {
var data = new google.visualization.DataTable();
data.addColumn('number', 'X');
data.addColumn('number', 'GPA');
data.addRows([
[0, 0],
[1, 10],
[2, 23],
[3, 17],
[4, 18],
]);
var options = {
hAxis: {
title: 'Total Distance'
},
vAxis: {
title: 'GPA'
}
};
var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));
chart.draw(data, options);
}
</script>
</head>
<body>
<div id="curve_chart" style="width: 900px; height: 500px"></div>
</body>
</html>
Here is the best answer I can come up with to help you.
In your question, you have to tackle different topics in javascript
get content of a local file in javascript
parse this content as a csv file (and make it a multidimensional array)
prepare the values to put in the chart
First, add the following two libraries : jQuery for the simplified ajax calls to the file and jquery-csv for an also simplified way to parse the content.
<script type="text/javascript" src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-csv/0.71/jquery.csv-0.71.min.js"></script>
Then, you have to re-route the charts callback : you have to point to a function that get asynchronously the file content (getFileContent in the example below).
Only in case of success, you can format the csv data into array.
And only then, you can serve the data to the chart by passing your formatted and sorted array to your drawbasic method.
Finally, you end up with that script
<script type="text/javascript">
google.charts.load('current', {
packages: ['corechart', 'line']
});
google.charts.setOnLoadCallback(getFileContent);
function getFileContent() {
var filePath = 'file:///path/to/file.csv';
// 1. Get local file content asynchronously
$.get(filePath, {}, function (data) {
console.log(arguments);
var lines = $.csv.toArrays(data); // 2. Parse the csv as a multidimensional array
var header = lines.shift(); // 3. Remove the header of the file
// 4. Sort the lines by the second column
lines.sort(function (a, b) {
if (a[1] === b[1]) {
return 0;
}
else {
return (a[1] < b[1]) ? -1 : 1;
}
});
// 5. Pass your lines to the draw method
drawBasic(lines);
}, 'text')
.fail(function () {
console.log(arguments);
})
;
}
function drawBasic(lines) {
var data = new google.visualization.DataTable();
data.addColumn('number', 'X');
data.addColumn('number', 'GPA');
for (i = 0; i < lines.length; i++) {
// 6. Don't forget to parse as float the numbers in the array, they are strings at this point
// You'll get a 'Type mismatch. Value 3,27 does not match type number' error if you don't
var xValue = parseFloat(lines[i][1]);
var yValue = parseFloat(lines[i][0]);
data.addRow([xValue, yValue]);
}
var options = {
hAxis: {
title: 'Total Distance'
},
vAxis: {
title: 'GPA'
}
};
var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));
chart.draw(data, options);
}
</script>
Don't forget to change the filepath in getFileContent, preceded by file://
I give credit to the answers in SO that helped me create this answer:
Javascript - read local text file
How to sort 2 dimensional array by column value?
Side note
In different conditions, it's much more common if you get csv (or, better with Javascript, JSON) via an HTTP call when working with Javascript to display data.
Local file reading may be reserved for server-side processing, that make this content available through HTTP.
With all the different ways to write a Json file, I wanted to learn more about how to write them and how to use them in a Google Chart.
First I started with making and using the following Json:
[
{
"Voetballer" : "Christiano Ronaldo",
"Jaar_2010" : 79000000.00,
"Jaar_2011" : 79700000.00,
"Jaar_2012" : 80000000.00,
"Jaar_2013" : 79500000.00,
"Jaar_2014" : 80000000.00,
"Jaar_2015" : 81000000.00
},
{
"Voetballer" : "Lionel Messi",
"Jaar_2010" : 55500000.00,
"Jaar_2011" : 60000000.00,
"Jaar_2012" : 61500000.00,
"Jaar_2013" : 62000000.00,
"Jaar_2014" : 63000000.00,
"Jaar_2015" : 64700000.00
}
(just a part of the Json)
And I made a chart with the help of Google's chart API and the following code:
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart()
{
$.getJSON('voetbal.json', function(data)
{
var dataTable = new google.visualization.DataTable();
dataTable.addColumn('string', 'jaar');
$.each(data, function(key, value)
{
dataTable.addColumn('number', value.Voetballer);
});
count=0;
$.each(data[0], function(key, value)
{
if (key != "Voetballer")
{
dataTable.addRows(1);
var Year = key.split("_");
dataTable.setValue(count, 0, Year[1]);
count++;
}
});
count=1;
$.each(data, function(i, object)
{
teller=0;
$.each(data[i], function(key, value)
{
if (key != "Voetballer")
{
dataTable.setValue(teller, count, value);
teller++;
}
});
count++;
});
var options =
{
colors : ['#8bbe24','#344d59','#d1ceb2','#c95338','#fcc800','#00a0e9','#601986','#e4ebe5'],
title : " Top earnings ",
seriesType: 'bars',
legend: {position: 'right'},
series: {11: {type: 'line'}}
};
var chart = new google.visualization.ComboChart(document.getElementById('visualization'));
chart.draw(dataTable, options);
});
}
</script>
</head>
<body>
<div id="visualization"></div>
</body>
This chart works great!
So I wanted to move on to a different Json file, create a correct file at first which became this one:
[
{
"round1": [
{
"playerA": 62,
"playerB": 98,
"playerC": 97,
"playerD": 94,
"playerE": 96
}
]
},
{
"round2": [
{
"playerA": 77,
"playerB": 40,
"playerC": 41,
"playerD": 99,
"playerE": 76
}
]
}
(it goes on until round 10)
How ever I can't get this Json file to work using the code from my previous chart so I changed the Json a bit to this:
[
{
"round": 1 [
{
"playerA": 62,
"playerB": 98,
"playerC": 97,
"playerD": 94,
"playerE": 96
}
]
},
In hope that it would make it easier but all I seem to manage is a empty screen, without errors.
Hopefully there's someone out there that can either point me in the right direction or show me what I'm doing wrong, my knowledge is very slim about Json files in general. I just figured I could use the working previous code and mainly change some names and be able to use pretty much the same code.
So my question in short: How can I use the second Json file I made with Google charts? And is it easier to use the code I've already once made, or go from scratch because of the different Json file? And if so, please tell me how/point me in the right way. All this Json stuff is confusing =)
The issue is that you changed the data structure of the JSON file. The first JSON file was an Array of objects [{obj1}, {obj2}...] and the second JSON file is an ARRAY of objects that have a key with an array as a value [{obj1:[array1]},{obj2:[array2]}...]. Both are completely valid JSON formats, but the API can only render the data under the first format. Please see this documentation to understand how you should be preparing the data for a google chart.
https://developers.google.com/chart/interactive/docs/basic_preparing_data
Please Help me....any plugin is there..?
I have searched for exporing excel and PDF in angularjs. using ng-grid.
Exporting ng-grid data to CSV and PDF format in angularjs
For csv export there is the ngGridCsvExportPlugin that you can find here
Just at a reference to the script and add the ngGridCsvExportPlugin to the gridOptions (and activate the footer too by adding showFooter : true to the gridOption)
$scope.gridOptions = {
data: 'myData',
plugins: [new ngGridCsvExportPlugin()],
showFooter: true,
};
A basic plunker where you can see it at work can be found here
You don't need any external plugin now. ng grid which new version is called now UI-Grid has native support. Method names are csvExport and pdfExport.
http://ui-grid.info/docs/#/tutorial/206_exporting_data
If you are able to do something outside of angular you could use https://github.com/Ziv-Barber/officegen for excel. See here https://stackoverflow.com/questions/18476921/angularjs-generating-a-pdf-client-side for pdfs.
I used jsPDF. It's the simplest ever.
Include it in your html:
<script src="jspdf.min.js"></script>
<!-- script src="jspdf.debug.js"></script--><!-- for development -->
Use it1:
var doc = new jsPDF();
doc.text(20, 20, 'Hello world.');
doc.save('Test.pdf');
And bind your button or whatever to this code.
Advanced Tip
I also found the jsPDF-AutoTable plugin-for-jsPDF extremely useful.
Include it in your html:
<script src="jspdf.plugin.autotable.js"></script>
In the controller, transfer data from ng-grid data to jsPDF, using jsPDF-AutoTable plugin.
Assuming you define your ng-grid table:
$scope.gridOptions = {
data: 'myData',
columnDefs: [
{field: 'user', displayName: 'User' /*,...*/ },
{field: 'email', displayName: 'Email' /*,...*/ },
{field: 'favoriteShruberry', displayName: 'Favorite Shrubbery' /*,...*/ }
]
};
... Then, in the function that generates the pdf:
var columns = [];
var rows = [];
// copy ng-grid's titles to pdf's table definition:
var allColumnDefs = $scope.gridOptions.columnDefs;
for ( var columnIdx in allColumnDefs ) {
var columnDef = allColumnDefs[columnIdx];
var newColumnDef = {
title: columnDef.displayName,
dataKey: columnDef.field
};
columns.push(newColumnDef);
}
// copy ng-grid's actual data to pdf's table:
var allRecords = $scope.myData;
for ( var recordIdx in allRecords ) {
var record = allRecords[recordIdx];
var newRow = {};
for ( var columnIdx in allColumnDefs ) {
var columnDef = allColumnDefs[columnIdx];
var value = record[columnDef.field];
if (value !== null) {
newRow[columnDef.field] = value;
}
}
rows.push(newRow);
}
var docName = 'favoriteShrubberies.pdf';
var pdfStyle = { styles: { overflow: 'linebreak' } } // this handles cells that contain really long text like in this comment, by auto-inserting a
// line break inside the cell, causing the whole line's height to increase accordingly
var doc = new jsPDF('p', 'pt'); // currently supports only 'pt'
doc.autoTable(columns, rows, pdfStyle);
doc.save(docName);
1 Example is straight from the jsPDF GitHub repo
Very late to this party, but I wrote a PDF output that works for me. There is a plunker, and it is available as a plugin for V2 of ng-grid, but it doesn't look like they have taken it through into V3 (but I just had a very quick peek, so I could be wrong).