My web app is about an Online Poll that manages Question's and answers, I can also vote on answers, so now I only need to show on a graphic the number of votes for each answer, I saw this Chart.js api so i'm trying to implement it to my app but having issues on Converting the Json objects the right way.
<html>
<head>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.js">
</script>
</head>
<body>
<div id="chart_container">
<canvas id="myChart" width="400" height="400"></canvas>
<script>
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar', data: {
labels: #Html.Raw(ViewBag.DataPoints)
datasets: [{
label: 'Numero de respostas',
data: #Html.Raw(ViewBag.DataPoints)
borderWidth: 1,
}]
},
options: {scales: {yAxes: [{ticks: {beginAtZero: true}}]}}});
</script>
</div>
Here is my controller code:
List<DataPoint> dataPoints = new List<DataPoint>();
foreach (var resposta in poolDbContext.Answers)
{
dataPoints.Add(new DataPoint(resposta.Text, answer.Votes.Count()));
}
ViewBag.DataPoints = JsonConvert.SerializeObject(dataPoints);
ViewBag.Data = question.Answers;
ViewBag.ObjectName = question.Text;
And here is my DataPoint Model:
[DataContract]
public class DataPoint
{
public DataPoint(string labels, double data)
{
this.Label = labels;
this.Y = data;
}
//Explicitly setting the name to be used while serializing to JSON.
[DataMember(Name = "labels")]
public string Label = "";
//Explicitly setting the name to be used while serializing to JSON.
[DataMember(Name = "data")]
public Nullable<double> Y = null;
}
I have managed to make it display the right number of bars but they don't have a value or an answer Text
EmptyBars Image
I would advice reading stack overflows help section on how to ask questions, if you want more responses at How to ask questions
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.js"></script>
</head>
<body>
<div id="chart_container">
<canvas id="myChart" width="400" height="400"></canvas>
</div>
<script>
var arrayOfAnswers = JSON.parse('#Html.Raw(Json.Encode(Model.Answers.ToList()))');
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: arrayOfAnswers,
datasets: [{
label: '# of Answers',
data: [//Enter data for all answers labels, corresponding to bars],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
</script>
</body>
</html>
This should work and also you can't do a foreach loop inside a javascript array
Related
I am having difficulties to get google charts to work in ASP.NET Core MVC. When using the example from google it works fine (Source: https://developers.google.com/chart/interactive/docs/gallery/columnchart):
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['bar']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Year', 'Sales', 'Expenses', 'Profit'],
['2014', 1000, 400, 200],
['2015', 1170, 460, 250],
['2016', 660, 1120, 300],
['2017', 1030, 540, 350]
]);
var options = {
chart: {
title: 'Company Performance',
subtitle: 'Sales, Expenses, and Profit: 2014-2017',
}
};
var chart = new google.charts.Bar(document.getElementById('columnchart_material'));
chart.draw(data, google.charts.Bar.convertOptions(options));
}
</script>
</head>
<body>
<div id="columnchart_material" style="width: 800px; height: 500px;"></div>
</body>
</html>
My problem is that my data has different lengths in columns, thus sticking to the example above I have sometimes ['Year', 'Sales'] or ['Year', 'Sales', 'Expenses'] and I am trying to make this plot dynamic.
I am using Viewbag to pass around my data, thus I have made available my model with:
#{
dataModel.ChartPlotData = ViewBag.ChartPlotData as ChartPlotData
}
I have defined a class holding my data:
public class ChartPlotData
{
public List<List<object>> Data;
public ChartPlotData() { Data = new List<List<object>>(); }
}
The data is filled via:
private ChartPlotData MockData()
{
var retVal = new ChartPlotData();
var line = new List<object>();
line.Add("Time");
line.Add("Test");
retVal.Data.Add(line);
line = new List<object>();
line.Add("0:05");
line.Add(0);
retVal.Data.Add(line);
line = new List<object>();
line.Add("0:10");
line.Add(1);
retVal.Data.Add(line);
return retVal;
}
Now I was trying to change the part in the plot data as:
var data = google.visualization.arrayToDataTable( #dataModel.ChartPlotData.Data )
It did not work. Next, I extended my class as:
public object[][] DataArray
{
get
{
var tmpLst = new List<object[]>();
foreach (var lstObj in Data)
{
tmpLst.Add(lstObj.ToArray());
}
return tmpLst.ToArray();
}
}
Still no luck. I tried various other things by instantiating the data as
var data = new google.visualization.DataTable();
then tried adding columns and setting cells like
// Add columns
data.addColumn('string', 'Employee Name');
data.addColumn('date', 'Start Date');
// Add empty rows
data.addRows(6);
data.setCell(0, 0, 'Mike');
data.setCell(0, 1, {v:new Date(2008,1,28), f:'February 28, 2008'});
data.setCell(1, 0, 'Bob');
data.setCell(1, 1, new Date(2007, 5, 1));
data.setCell(2, 0, 'Alice');
data.setCell(2, 1, new Date(2006, 7, 16));
data.setCell(3, 0, 'Frank');
but somehow I can not get it to work. Any help would be highly appreciated.
Edit:
I tried this:
var data = google.visualization.arrayToDataTable([
#for (var i = 0; i < 1; i++)
{
<text> ['Time','Test'],['00:00',0],['00:05',1] </text>
}
]);
It works. But when I replace it with a string containing the list, it stops working:
var data = google.visualization.arrayToDataTable([
#for (var i = 0; i < 1; i++)
{
<text> #dataModel.dataAsString </text>
}
]);
I can now narrow it down to the following problem. This works fine:
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', { 'packages': ['bar'] });
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable(
#for (var i = 0; i < 1; i++)
{
<text> [['Time', 'Test'], ['0:00', 0], ['0:05', 1]] </text>
}
);
var options = {
chart: {
title: 'Title',
subtitle: 'Some subtitle'
}
};
var chart = new google.charts.Bar(document.getElementById('columnchart_material'));
chart.draw(data, google.charts.Bar.convertOptions(options));
}
</script>
</head>
<body>
<div id="columnchart_material" style="width: 800px; height: 500px;"></div>
</body>
</html>
If I define a variable within my datamodel that includes exactly this string and replace
var data = google.visualization.arrayToDataTable(
#for (var i = 0; i < 1; i++)
{
<text> #dataModel.MyDataAsString </text>
}
);
it stops working.
I solved the problem. First, I created a field in html like
<p id="demo"></p>
Then in the java script one can use this to get the representation of the data:
var tmpData = google.visualization.arrayToDataTable([['Time', 'Test',], ['0:00', 1], ['0:05', 0.5]]);
document.getElementById("demo").innerHTML = tmpData.toJSON();
I then created a data class in C# that can generate this structure:
{"cols":[{"label":"Time","type":"string"},{"label":"Test","type":"number"}],"rows":[{"c":[{"v":"0:00"},{"v":1}]},{"c":[{"v":"0:05"},{"v":0.5}]}]}
Setting the value of the field using a variable
<p id="field">#StringRepresentation</p>
and then:
tmpJason = document.getElementById("field").innerHTML;
var data = new google.visualization.DataTable(tmpJason);
I am having a problem in building a pie chart with chart.js ..I am working in wix.com ..The problem i am facing is with 2 postmessage()..
Here is the page code....
import wixData from 'wix-data';
import { session } from 'wix-storage';
var name = session.getItem('name');
var platformName = session.getItem('platform');
import { getchampionranks } from 'backend/pcprofile.jsw';
$w.onReady(function () {
getchampionranks('pronil07').then(res => {
console.log(res);
var data = [];
var labels = [];
for (var i = 0; i <= res.length - 1; i++) {
data.push(res[i].Minutes.toString());
labels.push(res[i].champion.toString());
}
console.log(data);
console.log("Data length: " + data.length);
console.log(labels);
console.log("Label length: " + labels.length);
$w("#html1").postMessage(data);
//$w("#html1").postMessage(labels);
});
});
Here is the iframe code...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src ="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.js"></script>
</head>
<body onLoad="ready()">
<canvas id="myChart" width="146" height="149"></canvas>
<script>
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: [],
datasets: [{
label: 'wins/loss',
data: [],
backgroundColor: [
'#3ddba1',
'#e02a2a',
'#4286f4',
'#6897e2',
'#444a54',
'#45a567',
'#91a545',
'#a87534',
'#8c6e8a'
],
borderWidth: 1
}]
},
options: {
cutoutPercentage : 0,
rotation: Math.PI * 0.8,
legend:{
display: false,
position: 'bottom',
},
animation: {
easing: 'easeOutElastic',
Steps: 100,
animateRotate : true,
animateScale : true
}
}
});
window.onmessage = function(event){
myChart.data.datasets[0].data = event.data;
myChart.update();
};
function ready(){
window.parent.postMessage({"type":"ready"}, "*");
}
</script>
</body>
</html>
On doing this..i am getting the result like this..
Result
I am getting the chart with the data array..but the labels is undefined..
And if i unquote the postmessage(labels) and send both data and labels via 2 postmessage()..the chart don't form...
I need to send both data and labels array to the iframe from page code...
Any solution?????
This is easiest done by sending both the data and the labels from your page code in one object. Then in the HTML element, you can set the chart's data and labels using that object.
In your case, that would look something like this:
Page Code:
let info = {data:data, labels:labels};
$w("#html1").postMessage(info);
HTML Element Code:
window.onmessage = function(event){
myChart.data.datasets[0].data = event.data.data;
myChart.data.labels = event.data.labels;
myChart.update();
};
You are right! This is the easiest way.
Here is the page code...
var data = [];
for (var i = 1; i < 7; i++) {
var _temp = Math.log10(i);
data.push(_temp);
}
var labels = ["September", "October", "Novemver", "December", "January", "February"];
$w.onReady(() => {
console.log("Data length: " + data.length);
console.log(data);
console.log("Label length: " + labels.length);
console.log(labels);
$w("#html1").onMessage((event) => {
let info = { data: data, labels: labels };
if (event.data.type === 'ready') {
$w("#html1").postMessage(info);
}
});
});
Here is the html code...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src ="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.js">
</script>
</head>
<body onLoad="ready()">
<canvas id="myChart" width="250" height="200"></canvas>
<script>
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: [],
datasets: [{
label: 'Our activity',
data: []
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
window.onmessage = function(event){
myChart.data.datasets[0].data = event.data.data;
myChart.data.labels = event.data.labels;
myChart.update();
};
function ready(){
window.parent.postMessage({"type":"ready"}, "*");
}
I'm trying to setup a Web Page using the same data that is being pulled for the first chart. Data is being pulled by an edmx entity model. The code below works for single graph. I want to add a Pie Chart on the same page as well using the same data. All the examples I've seen are for graphs using static data. My code is below, I know I would need to just reproduce what I have in some fashion. Thanks,
<script type="text/javascript" src="https://www.google.com/jsapi">
</script>
#section Scripts{
<script>
$(document).ready(function () {
//Load Data Here
var chartData = null;
$.ajax({
url: '/GoogleChart/GetSalesData',
type: 'GET',
dataType: 'json',
data: '',
success: function (d) {
chartData = d;
},
error: function () {
alert('Error!');
}
}).done(function () {
drawChart(chartData);
});
});
function drawChart(d) {
var chartData = d;
var data = null;
data = google.visualization.arrayToDataTable(chartData);
var view = new google.visualization.DataView(data);
view.setColumns([0, {
type: 'number',
label: data.getColumnLabel(0),
calc: function () { return 0; }
}, {
type: 'number',
label: data.getColumnLabel(1),
calc: function () { return 0; }
}, {
type: 'number',
label: data.getColumnLabel(2),
calc: function () { return 0; }
}]);
var chart = new google.visualization.ColumnChart(document.getElementById('visualization1'));
var options = {
}
var runFirstTime = google.visualization.events.addListener(chart, 'ready', function () {
google.visualization.events.removeListener(runFirstTime);
chart.draw(data, options);
});
chart.draw(view, options);
}
google.load('visualization', '1', { packages: ['corechart'] });
</script>
<div id="visualization1" style="width:900px; height:500px"></div>
}
first, recommend using...
<script src="https://www.gstatic.com/charts/loader.js"></script>
not...
<script src="https://www.google.com/jsapi"></script>
according to the release notes...
The version of Google Charts that remains available via the jsapi loader is no longer being updated consistently. Please use the new gstatic loader.js from now on.
note: the load statement will be the only difference, as seen below...
next, you can draw as many charts as necessary,
after the load statement has completed
you must set a callback to know for sure,
that google charts has loaded all of the requested packages...
multiple packages can be loaded at the same time
google.charts.load('current', {
callback: loadData,
packages: ['corechart', 'table']
});
the callback will also wait for the document to finish loading...
as such, $(document).ready isn't needed
recommend setup similar to following...
<script src="https://www.gstatic.com/charts/loader.js"></script>
#section Scripts{
<script>
function loadData() {
$.ajax({
url: '/GoogleChart/GetSalesData',
type: 'GET',
dataType: 'json',
data: '',
}).fail(function (jq, text, errMsg) {
console.log(text + ': ' + errMsg);
}).done(function (jsonData) {
drawCharts(jsonData);
});
}
function drawCharts(jsonData) {
var chartData = google.visualization.arrayToDataTable(jsonData);
var chartCol = new google.visualization.ColumnChart(document.getElementById('visualization-col'));
chartCol.draw(chartData);
var chartPie = new google.visualization.PieChart(document.getElementById('visualization-pie'));
chartPie.draw(chartData);
var chartTable = new google.visualization.Table(document.getElementById('visualization-table'));
chartTable.draw(chartData);
}
google.charts.load('current', {
callback: loadData,
packages: ['corechart', 'table']
});
</script>
<div id="visualization-col"></div>
<div id="visualization-pie"></div>
<div id="visualization-table"></div>
}
note: each chart has a specific data format
although most of the charts in 'corechart' will be fine,
not all charts may work with the same data table...
I'm beginner in asp.net and highchart control,want to use highchart control in my web application web form,for that purpose read this tutorial:
this tutorial
and write this web service in my project:
public class cityPopulation
{
public string city_name { get; set; }
public int population { get; set; }
public string id { get; set; }
}
[WebMethod]
public List<cityPopulation> getCityPopulation(List<string> pData)
{
List<cityPopulation> p = new List<cityPopulation>();
cityPopulation cpData = new cityPopulation();
cpData.city_name = "tabriz";
cpData.population = 100;
p.Add(cpData);
return p;
}
that web service name is this:
WebService1.asmx
and in my web form write this script :
<script type="text/javascript">
function drawPieChart(seriesData) {
$('#container').highcharts({
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie'
},
title: {
text: 'Population percentage city wise'
},
tooltip: {
pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.percentage:.1f} %',
style: {
color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
}
}
}
},
series: [{
name: "Brands",
colorByPoint: true,
data: seriesData
}]
});
}
$("#btnCreatePieChart").on('click', function (e) {
var pData = [];
pData[0] = $("#ddlyear").val();
var jsonData = JSON.stringify({ pData: pData });
$.ajax({
type: "POST",
url: "WebService1.asmx/getCityPopulation",
data: jsonData,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: OnSuccess_,
error: OnErrorCall_
});
function OnSuccess_(response) {
var aData = response.d;
var arr = []
$.map(aData, function (item, index) {
var i = [item.city_name, item.population];
var obj = {};
obj.name = item.city_name;
obj.y = item.population;
arr.push(obj);
});
var myJsonString = JSON.stringify(arr);
var jsonArray = JSON.parse(JSON.stringify(arr));
drawPieChart(jsonArray);
}
function OnErrorCall_(response) {
alert("Whoops something went wrong!");
}
e.preventDefault();
});
//*
</script>
before that script write this code:
<script src="Scripts/jquery-2.2.3.min.js"></script>
<script src="Scripts/Highcharts-4.0.1/js/highcharts.js"></script>
and write this html code:
<select id="ddlyear">
<option>2010</option>
<option>2011</option>
<option>2012</option>
<option>2013</option>
<option>2014</option>
<option>2015</option>
</select>
<button id="btnCreatePieChart">Show </button>
<br />
<div>
<div id="container" style="width: 500px; height: 500px"></div>
</div>
but when i run project and fire the button,can not see anything,and chart not show to me,what happen?is my code incorrect?how can i solve that problem?thanks.
i think ajax can not call the web service!
I'm facing a strange issue with autocomplete.
First issue:
based on the tutorial found here, only the first letter of the found items is showing in the list of autocomplete items
Here is an illustration:
My action at debug time
Dummy data returned, always the same regardless of the search pattern just for testing
In the rendered view, this is what happens:
The Javascript for autocomplete of this scenario is as follows:
$("#Email").autocomplete('#Url.Action("FindEmail", "Administration")',
{
dataType: 'json',
parse: function(data) {
var rows = new Array();
for (var i = 0; i < data.length; i++) {
rows[i] = {
data: data[i].Value,
value: data[i].Value,
result: data[i].Value
};
}
return rows;
},
width: 300,
minLength: 3,
highlight: false,
multiple: false
});
Second issue:
I've changed my code to work with a more comfortable Ajax call for me that depends on Model mapping rather than sending a q and limit parameters as in the previous tutorial, and as I've seen in many other tutorials, but the Ajax call isn't firing, not even giving me an error.
My code for this scenario is based on this Stack Overflow Answer
Here is my controller and view code related:
//[HttpPost]
[SpecializedContextFilter]
[Authorize]
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public JsonResult FindEmail(RegistrationModel model) //Notice the use of model instead of string q and string limit
{
//Just a dummy implementation
var rez = new List<ValueModel>
{
new ValueModel {Description = "atest1#test.com", Value = "atest1#test.com"},
new ValueModel {Description = "atest2#test.com", Value = "atest2#test.com"},
new ValueModel {Description = "atest3#test.com", Value = "atest3#test.com"},
new ValueModel {Description = "atest4#test.com", Value = "atest4#test.com"}
};
//var retValue = rez.Select(r => new { email = r.Value }).OrderBy(x => x).Take(10);
//return Json(retValue, JsonRequestBehavior.AllowGet);
return Json(rez, JsonRequestBehavior.AllowGet);
}
View JavaScript:
$("#Email").autocomplete({
source: function(request, response) {
$.ajax({
url: '#Url.Action("FindEmail", "Administration")',
type: "POST",
dataType: "json",
data: { email: $("#Email").val(), conferenceId: $("#ConferenceId").val() },
success: function(data) {
response($.map(data, function(item) {
return { label: item.Value, value: item.Value, id: item.Value };
}));
},
select: function(event, ui) {
$("input[type=hidden]").val(ui.item.id);
}
});
}
});
Firefox console view:
I've tried a lot of codes for the second scenario, most of them are Stack Overflow answers, but nothing is happening!
I'm my missing anything ?
Note: jQuery plugins are included, Ajax is already working in the same page, so I'm not sure whats the problem
Thanks for any help.
Here is a full working example, see screen grab.
These are the steps that I had take to get the second example working.
Script-references/Markup/Js
<script src="~/Scripts/jquery-1.8.2.js"></script>
<script src="~/Scripts/jquery-ui-1.8.24.min.js"></script>
<input id="ConferenceId" value="1" />
<div class="ui-widget">
<label for="Email">Email: </label>
<input id="Email">
</div>
<script type="text/javascript">
$("#Email").autocomplete({
source: function (request, response) {
$.ajax({
url: '#Url.Action("FindEmail", "Administration")',
type: "POST",
dataType: "json",
data: { email: $("#Email").val(), conferenceId: $("#ConferenceId").val() },
success: function (data) {
response($.map(data, function (item) {
return { label: item.Value, value: item.Value, id: item.Value };
}));
},
select: function (event, ui) {
$("input[type=hidden]").val(ui.item.id);
}
});
}
});
</script>
Models
public class RegistrationModel
{
public string Email { get; set; }
public string ConferenceId { get; set; }
}
public class ValueModel
{
public string Description { get; set; }
public string Value { get; set; }
}
Controller Action
I had to add the [HttpPost] attribute.
[HttpPost]
public JsonResult FindEmail(RegistrationModel model) //Notice the use of model instead of string q and string limit
{
//Just a dummy implementation
var rez = new List<ValueModel>
{
new ValueModel {Description = "atest1#test.com", Value = "atest1#test.com"},
new ValueModel {Description = "atest2#test.com", Value = "atest2#test.com"},
new ValueModel {Description = "atest3#test.com", Value = "atest3#test.com"},
new ValueModel {Description = "atest4#test.com", Value = "atest4#test.com"}
};
return Json(rez, JsonRequestBehavior.AllowGet);
}
Screen grab