I'm trying to populate a data table from a List object and then display the result in a pie chart. For some reason which I cannot identify the pie chart is not showing in the browser (blank page). Below is my code. Can someone try to run this code and identify were is the error!... since I cannot identify were I'm wrong.
The Default.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(drawChart);
function drawChart(dataValues) {
var data = new google.visualization.DataTable();
data.AddColumn('string', 'Locality');
data.AddColumn('number', 'Frequency');
for (var i = 0; i < dataValues.length; i++) {
data.AddRow(dataValues[i].aString, dataValues[i].anInt);
}
var options = { 'title': 'Pie Chart Test',
'width': 900,
'height': 500
};
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
}
</script>
</head>
<body>
<div id="piechart" style="width: 900px; height: 500px;"></div>
</body>
</html>
Code Behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Script.Serialization;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
List<Items> dataList = new List<Items>();
dataList.Add(new Items("A", 10));
dataList.Add(new Items("B", 20));
dataList.Add(new Items("C", 30));
JavaScriptSerializer jss = new JavaScriptSerializer();
ClientScript.RegisterStartupScript(this.GetType(), "Test", string.Format("<script type=\"text/javascript\">drawVisualization({0});</script>", jss.Serialize(dataList)));
}
}
public class Items
{
public string aString = "";
public int anInt = 0;
public Items(string _aString, int _anInt)
{
aString = _aString;
anInt = _anInt;
}
}
}
Thank You
JavaScript is case sensitive. The method names are .addColumn() and .addRow(), but you are using .AddColumn() and .AddRow(). Check your JavaScript console for errors. You should find a message saying something like undefined is not a function.
The .addRow() method takes an array as its argument, but you are passing in two scalar values. Wrap those up in square brackets: data.addRow([dataValues[i].aString, dataValues[i].anInt]).
You may also run into issues with your use of RegisterStartupScript(). Your startup script may run before the visualization package has finished loading. Instead, I would embed the value in a hidden field on the page and read that value from your script.
<asp:HiddenField runat="server" ID="ChartData" />
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
List<Items> dataList = new List<Items>();
dataList.Add(new Items("A", 10));
dataList.Add(new Items("B", 20));
dataList.Add(new Items("C", 30));
JavaScriptSerializer jss = new JavaScriptSerializer();
this.ChartData.Value = jss.Serialize(dataList);
}
}
function drawChart() {
var dataValues = JSON.parse(document.getElementById("<%= ChartData.ClientID %>").value);
// The rest of the function as written
}
Snippet with all the changes applied:
google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(drawChart);
function drawChart() {
var dataValues = JSON.parse(document.getElementById("ChartData").value);
var data = new google.visualization.DataTable();
data.addColumn('string', 'Locality');
data.addColumn('number', 'Frequency');
for (var i = 0; i < dataValues.length; i++) {
data.addRow([dataValues[i].aString, dataValues[i].anInt]);
}
var options = { 'title': 'Pie Chart Test',
'width': 900,
'height': 500
};
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
}
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<input type="hidden" id="ChartData" value="[{"aString":"A","anInt":10},{"aString":"B","anInt":20},{"aString":"C","anInt":30}]" />
<div id="piechart" style="width: 900px; height: 500px;"></div>
Related
I'm trying to implement a new project. I want to write an SQL table dynamically into e.g. an asp:gridview. And this grid should be editable.
I found some solutions, but they were all static. But it is essential that the table is dynamic, because I want to include different SQL tables in the grid. (The SQL tables sometimes change, columns are removed or new ones are added. Therefore a static solution is not applicable.
Ideally, the editing function should work like in an Excel document. After changing the data, it should be written back to the SQL table with a save button.
Is that even possible? I haven't found a solution to this problem in at least the last 4 hours.
Thank you for your help
Greetings
Update
//HTML Code:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>Personaldaten</h1>
<asp:GridView ID="personal_data" AutoGenerateColumns="true" runat="server"></asp:GridView>
<asp:Button runat="server" ID="button1" text="Save"/>
</div>
</form>
</body>
</html>
//Code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace Editable_SQL_Table
{
public partial class table : System.Web.UI.Page
{
SqlDataAdapter sda;
SqlCommandBuilder scb;
DataTable dt;
public form1()
{
InitializeComponent();
}
public void form1_Load(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(#"Server = (localdb)\\MSSQLLocalDB; Database = Personal; Trusted_Connection = True; MultipleActiveResultSets = true");
sda = new SqlDataAdapter(#"SELECT* FROM dbo.MyTable", con);
dt = new DataTable();
sda.Fill(dt);
dataGridView1.DataSource = dt;
}
private void button1_Click(object sender, EventArgs e)
{
scb = new SqlCommandBuilder(sda);
sda.Update(dt);
MessageBox.Show("Table updated");
}
}
}
I tried to use the coding from user2980341 but I have a problem with "dataGridView1.DataSource = dt;" I think for "dataGridView1" I should use the id from my Gridview, but I does not work. The debugger says, that he does not recognise "personal_data". Also the function "InitializeComponent();" is undefinded.
Thanks for any further help, I am currently working on the following solution:
//HTML
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="table.aspx.cs" Inherits="Editable_SQL_Table.table" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>Personaldaten</h1>
<asp:GridView ID="personal_data" AutoGenerateEditButton="true" AutoGenerateColumns="true" runat="server" OnRowUpdating="personal_data_RowUpdating" OnRowCancelingEdit="personal_data_RowCancelingEdit" OnRowEditing="personal_data_RowEditing"></asp:GridView>
</div>
</form>
</body>
</html>
//Code behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace Editable_SQL_Table
{
public partial class table : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string table = "dbo.Mitarbeiter";
string query = "SELECT * FROM" + " " + table;
string ConnectionString = "Server = (localdb)\\MSSQLLocalDB; Database = Personal; Trusted_Connection = True; MultipleActiveResultSets = true";
using (SqlConnection myConnection = new SqlConnection(ConnectionString))
{
using (SqlCommand cmd = new SqlCommand(query, myConnection))
{
myConnection.Open();
SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
DataTable dt = new DataTable();
dt.Load(dr);
personal_data.DataSource = dt;
personal_data.DataBind();
}
}
}
protected void personal_data_RowEditing(object sender, GridViewEditEventArgs e)
{
personal_data.EditIndex = e.NewEditIndex;
}
protected void personal_data_RowUpdating(object sender, GridViewEditEventArgs e)
{
//personal_data.EditIndex = e.NewEditIndex;
}
protected void personal_data_RowCancelingEdit(object sender, GridViewEditEventArgs e)
{
//personal_data.EditIndex = e.NewEditIndex;
}
}
}
Perhaps something like this:
Add DataGridView and a Button element on your form. Then append this code to your elements:
using System.Data.SqlClient;
namespace test
{
public partial class Form1 : Form
{
SqlDataAdapter sda;
SqlCommandBuilder scb;
DataTable dt;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection (#"Server=myServerAddress;Database=myDataBase;Trusted_Connection=True;");
sda = new SqlDataAdapter(#"SELECT* FROM dbo.MyTable", con);
dt = new DataTable();
sda.Fill(dt);
dataGridView1.DataSource = dt;
}
private void button1_Click(object sender, EventArgs e)
{
scb = new SqlCommandBuilder(sda);
sda.Update(dt);
MessageBox.Show("Table updated");
}
}
}
This program connects to your SQL database and retrives an SQL table from that database. Changes to databse are updated using button1. You cannot however remove or add columns trough this solution.
I want to show data stored in Array-list in body of Mailbox. User can then add mail ids in To: according to his/her convenience and send the mail.
But its throwing JavaScript error when large amount of data is sent to body.
Here is the test code of .aspx page:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript">
function mail()
{
var array_store;
array_store = document.getElementById("array_store");
var vs = array_store.value;
window.location.href = "mailto: &body=" + encodeURIComponent(decodeURIComponent(vs));
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:Button ID="Button_mail" runat="server" Text="OpenInMailBox" OnClientClick="mail()" />
<input type="hidden" id="array_store" name = "ArrayStore" value = '<%=this.ArrayStore %>' />
</form>
</body>
</html>
Code of .CS page :
public partial class mailto_check : System.Web.UI.Page
{
protected System.Text.StringBuilder ArrayStore = new System.Text.StringBuilder();
string str = "";
protected void Page_Load(object sender, EventArgs e)
{
ArrayList al = new ArrayList();
al.Add("Test1");
al.Add("hello ");
al.Add("Testing");
try
{
for (int y = 0; y < al.Count; y++)
{
str = al[y].ToString();
this.ArrayStore.Append(str+",%0D");
}
}
catch (Exception ex)
{
Response.Write(ex.ToString());
}
}
}
for large data I tested it by adding values to array-list.
Please help me with this.
Thanks in advance for positive answers.
When I press the button named calendar I am directed to the controller where it is called the main view which contains two DatePickers. After I select two dates and click on the submit button , I am directed in the controller in the method called "Plotting" that would open a new view that display a chart .My question is , can i display the chart view to be seen under the main view with the two DatePickers because if i want to select other dates to not have to press the back button?
Here is my code from the controller which leads me to the main view :
public ActionResult Calendar()
{
ChartDate objdatemodel = new ChartDate();
return View("Calendar",objdatemodel);
}
Here is the code for the main view named Calendar
#model Plotting.Models.ChartDate
#{
ViewBag.Title = "jQuery UI Datepicker Calender Control In Asp.Net Mvc Application";
}
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.0/themes/smoothness/jquery-ui.css">
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script src="http://code.jquery.com/ui/1.11.0/jquery-ui.js"></script>
<h2>
Datepicker Calender
</h2>
<div id="yourviewDiv"></div>
#using (Html.BeginForm("Plotting", "Greenhouse"))
{
<table>
<tr>
<td>
<p>
Start Date: #Html.TextBoxFor(m => m.StartDate, new { #id = "txtdatepicker1", #style = "width:200px;" })
</p>
</td>
<td>
<p>
End Date: #Html.TextBoxFor(m => m.EndDate, new { #id = "txtdatepicker2", #style = "width:200px;" })
</p>
</td>
</tr>
</table>
<input type="submit" value="Submit" />
}
<script>
$(function () {
$("#txtdatepicker1").datepicker();
});
$(function () {
$("#txtdatepicker2").datepicker();
});
</script>
Here is the code from the controller for the view plotting:
public ActionResult Plotting(ChartDate objdatemodel)
{
ChartDate cDate = new ChartDate();
cDate.DateData = new DateChart();
cDate.DateTitle = "Day";
cDate.HumidityTitle1 = "Senzor 1";
cDate.HumidityTitlle2 = "Senzor 2";
List<Greenhouse> greenhouse = dal.FindDatesByInterval(objdatemodel.StartDate , objdatemodel.EndDate);
String day = "";
String humidity1 = "";
String humidity2 = "";
for (int i = 0; i < greenhouse.Count - 1; i++)
{
day += greenhouse[i].DateTime.Day + ",";
humidity1 += greenhouse[i].Humidity1 + ",";
humidity2 += greenhouse[i].Humidity2 + ",";
}
day += greenhouse[greenhouse.Count - 1].DateTime.Day;
humidity1 += greenhouse[greenhouse.Count - 1].Humidity1;
humidity2 += greenhouse[greenhouse.Count - 1].Humidity2;
DateChart obj = new DateChart();
/*Get the data from databse and prepare the chart record data in string form.*/
obj.Date = day;
obj.Humidity1 = humidity1;
obj.Humidity2 = humidity2;
cDate.DateData = obj;
return View("Plotting",cDate);
}
And here is the code for the Plotting view :
#model Plotting.Models.ChartDate
#{
ViewBag.Title = "How To Create Dynamic Google Column Chart In an Asp.Net MVC Application Using C# ";
}
<fieldset>
<legend><strong>Greenhouse</strong></legend>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(drawChart);
function drawChart() {
// Create and populate the data table.
var days = [#Model.DateData.Date];
var humidities1 = [#Model.DateData.Humidity1];
var humidities2 = [#Model.DateData.Humidity2];
var data = new google.visualization.DataTable();
data.addColumn('string', '#Model.DateTitle');
data.addColumn('number', '#Model.HumidityTitle1');
data.addColumn('number', '#Model.HumidityTitlle2');
for (i = 0; i < days.length; i++) {
data.addRow([days[i].toString(), humidities1[i], humidities2[i]]);
}
var options = {
title: 'Humidities Values',
hAxis: { title: '#Model.DateTitle', titleTextStyle: { color: 'black' } }
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
<div id="chart_div" style="width: auto; height: auto;">
</div>
</fieldset>
Currently the code works , but if I want to put another chart I have to press the back button . You can put the two sites view the same view ? Thank you .
I'm programming an ASP.Net MVC page and I'm using data from the server to create a Google chart. The x-axis is the date. The y-axis is the value. There are 2 lines of data being plotted to compare. Here is the relevant code:
#model IEnumerable<Tuple<DateTime,int,int>>
<div id="chart_div_2" style="width: 900px; height: 500px;"></div>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(drawChart);
function drawChart() {
var arr = [['Year', 'Sales', 'Expenses']];
//Using the Razor Model to create a Javascript array.
var arr2 = [
#foreach(var row in Model)
{
#:["#row.Item1.ToString("MMM d")", #row.Item2, #row.Item3],
}
];
for (var i = 0; i < arr2.length; i++)
{
arr.push(arr2[i]);
}
var data = google.visualization.arrayToDataTable(arr);
var chart = new google.visualization.LineChart(document.getElementById('chart_div_2'));
chart.draw(data);
}
</script>
First of all, this code does actually work. Creating arr2 this way does turn a Razor model into something that I can use. However, my nose says code smell. It says that throwing together two languages razor and Javascript, which have somewhat similar C-based programming flow syntax could be confusing to the next person that comes along and tries to read it.
Is there a better way to write this?
However, my nose says code smell.
Oh yeah it stinks, I can feel it.
Is there a better way to write this?
Of course. Never build JSON manually as you did by mixing the 2 languages and writing loops and stuff. Use a JSON serializer:
#model IEnumerable<Tuple<DateTime,int,int>>
<div id="chart_div_2" style="width: 900px; height: 500px;"></div>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(drawChart);
function drawChart() {
var arr = #Html.Raw(
Json.Encode(
new object[] { new[] { "Year", "Sales", "Expenses" } }
.Concat(
Model.Select(x => new object[]
{
x.Item1.ToString("MMM d"),
x.Item2,
x.Item3
})
)
)
);
var data = google.visualization.arrayToDataTable(arr);
var chart = new google.visualization.LineChart(document.getElementById('chart_div_2'));
chart.draw(data);
}
</script>
This will generate an equivalent code markup as yours but the whole model manipulation and encoding is done on the server. You could also write a custom HTML helper in order to simplify your code to this:
public static class ChartExtensions
{
public static IHtmlString ToChartData(
this IEnumerable<Tuple<DateTime, int, int>> model,
params string[] titles
)
{
return new HtmlString(
Json.Encode(
new object[] { titles }
.Concat(
model.Select(x => new object[]
{
x.Item1.ToString("MMM d"),
x.Item2,
x.Item3
})
)
)
);
}
}
and then in your view:
#model IEnumerable<Tuple<DateTime,int,int>>
<div id="chart_div_2" style="width: 900px; height: 500px;"></div>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(drawChart);
function drawChart() {
var arr = #Model.ToChartData("Year", "Sales", "Expenses");
var data = google.visualization.arrayToDataTable(arr);
var chart = new google.visualization.LineChart(document.getElementById('chart_div_2'));
chart.draw(data);
}
</script>
Here is my controller class:
global class MyJSController {
public static String objj { get; set; }
#RemoteAction
public static String getObject_name(){
return objj;
}
#RemoteAction
public static void setObject_name(String s){
objj=s;
}
public String accountName { get; set; }
public static Account account { get; set; }
public static List<Order__c> order{get;set;}
public static List<Units__C>unit{get;set;}
public static List<Widget__c> widget{get;set;}
public MyJSController() {
setObject_name('Order');
} // empty constructor
#RemoteAction
global static Account getAccount(String accountName) {
account = [SELECT id, name, phone, type, numberofemployees
FROM Account WHERE name = :accountName];
return account;
}
#RemoteAction
global static Order__c[] getOrder(){
return ([SELECT id,Name,Date__c,Inbound_Orders__c,Outbound_Orders__c from Order__c]);
}
#RemoteAction
global static List<Units__c> getUnits(){
unit=[SELECT id,Name,Date__c,Inbound_Units__c,Outbound_Units__c from Units__c];
return unit;
}
#RemoteAction
global static List<Widget__c> getWidget(){
widget=[SELECT id,Name,Date__c,Inbound_Widgets__c,Outbound_Widgets__c from Widget__c];
return widget;
}
}
And here is my visualforce page:
<apex:page controller="MyJSController">
<apex:form >
<apex:selectList id="chooseColor" value="{!object_name}" size="1" onchange="initCharts()" >
<apex:selectOption itemValue="Order" itemLabel="Order"/>
<apex:selectOption itemValue="Unit" itemLabel="Unit"/>
<apex:selectOption itemValue="Widget" itemLabel="Widget"/>
</apex:selectList>
</apex:form>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
// Load the Visualization API and the piechart package.
google.load('visualization', '1.0', {'packages':['corechart']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(initCharts);
function initCharts() {
// Following the usual Remoting syntax
// [<namespace>.]<controller>.<method>([params...,] <callbackFunction>(result, event) {...}
// namespace : abhinav
// controller : GoogleChartsController
// method : loadOpps
MyJSController.getOrder(
function(result, event){
// load Column chart
var data = new google.visualization.DataTable();
data.addColumn('string', 'Topping');
data.addColumn('number', 'Slices');
for(var i =0; i<result.length;i++){
var r = result[i];
data.addRow([r.Name,r.Inbound_Orders__c]);
}
var data1=new google.visualization.DataTable();
data1.addColumn('string','Topping');
data1.addColumn('number','Slices');
for(var i=0;i<result.length;i++)
{
var r=result[i];
data1.addRow([r.Name,r.Inbound_Orders__c]);
}
// Set chart options
var options = {'title':'How Much Pizza I Ate Last Night',
'width':400,
'height':300};
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.AreaChart(document.getElementById('chart_div'));
var chart1= new google.visualization.AreaChart(document.getElementById('chart_hh'));
chart.draw(data, options);
chart1.draw(data1,options); }, {escape:true});
MyJSController.getObject_name(function(event,result){
alert('Hello'+result);
document.getElementById('dddd').innerHTML=String.ValueOf(result); },{escape:true});
}
</script>
<div id="chart_div" ></div>
<div id="chart_hh"></div>
<div id="dddd">Helloojjfs</div>
</apex:page>
When I call MyJSController.getObject_name in script tag (4th last line in script tag) in result I am getting [Object Object]. But I need String Order which I initialize in the constructor. Can you please tell me where I am wrong and to rectify this mistake?
I believe the issue is that your argument names are backwards. It should be:
MyJSController.getObject_name(function(result, event)
So the alert you are getting of an object is actually the event object.