How to map json output from [WebMethod] to d3.js bar charts - c#

Hi I am new to d3.js.I have this following [WebMethod] in .aspx file:
[WebMethod]
public static List<Product> GetProductsLINQ()
{
List<Product> lstProducts = new List<Product>();
DataTable dtProducts = new DataTable();
string sqlQuery = "SELECT Product_Name, Purchase_Price FROM tblProductMaster";
string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["BTrax"].ConnectionString;
SqlConnection conn = new SqlConnection(connectionString);
SqlDataAdapter da = new SqlDataAdapter(sqlQuery, conn);
da.Fill(dtProducts);
var productslinq = (from products in dtProducts.AsEnumerable()
select new
{
//Product_Id = products.Field<decimal>("Product_Id"),
Product_Name = products.Field<string>("Product_Name"),
Product_Code = products.Field<decimal>("Purchase_Price"),
}).ToList();
foreach (var product in productslinq)
{
//lstProducts.Add(new Product(product.Product_Id,product.Product_Name, product.Product_Code));
lstProducts.Add(new Product(product.Product_Name, product.Product_Code));
}
return lstProducts;
}
Now, how to use this output as an input to d3.js bar chart? I tried the below script by pasting it in body tag in .aspx file but it din't help.Please provide me a solution.Thanks in Advance.
<script>
var d;
var svg = d3.select("svg"),
margin = { top: 20, right: 20, bottom: 30, left: 40 },
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
y = d3.scaleLinear().rangeRound([height, 0]);
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.json("WebForm1.aspx/GetProductsLINQ", function (json) {
d=json
d.Product_Code = +d.Product_Code;
return d;
}, function (error, data) {
if (error) throw error;
x.domain(data.map(function (d) { return d.Product_Name; }));
y.domain([0, d3.max(data, function (d) { return d.Product_Code; })]);
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y).ticks(10, "%"))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("Frequency");
g.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function (d) { return x(d.Product_Name); })
.attr("y", function (d) { return y(d.Product_Code); })
.attr("width", x.bandwidth())
.attr("height", function (d) { return height - y(d.Product_Code); });
});
</script>
I have referred d3.js with the following link,
<script src="https://d3js.org/d3.v4.min.js"></script>

Unlike d3.csv and d3.tsv, d3.json does not accept an accessor function (or row function).
According to the API, these are the arguments of a d3.csv:
d3.csv(url, row, callback);
Compare with the argument of a d3.json:
d3.json(url[, callback])
I'm pasting your function and commenting out everything that is an accessor (row) function:
d3.json("WebForm1.aspx/GetProductsLINQ", //function (json) {
//d=json
//d.Product_Code = +d.Product_Code;
//return d;
//},
function (error, data) {
if (error) throw error;
So, it should be only:
d3.json("WebForm1.aspx/GetProductsLINQ", function (error, data) {
if (error) throw error;
And then, right after it, put your accessor (row) function inside d3.json as a forEach:
data.forEach(function(d){
d.Product_Code = +d.Product_Code;
});

Related

MVC add to JSON object

I am trying to add many json lists to another json object to send to the view, however I am not sure how to add all of them to a single object as it is not always certain how many lists there will be.
Here is what I have so far in my controller, I get each list from a LINQ query from my model and convert it to a list that is stored in a var.
/////////////////////////////////////////////
//Actions for Export //
///////////////////////////////////////////
public JsonResult GetInfoToExport()
{
using (InsertModelEntities dc = new InsertModelEntities())
{
CleintEntities cleints = new CleintEntities();
var ClientList = cleints.Clients.ToList();
var JsonToSend = new JsonResult();
foreach (var Company in ClientList)
{
var ClientInfo = (from E in dc.EventsAllLocations
join C in cleints.Clients on E.CompanyName equals C.Company
where C.Company == Company.ToString() && E.Start.Year == DateTime.Now.Year && E.Start.Month == DateTime.Now.Month
select new
{
Company = E.CompanyName,
Location = E.Location,
HoursPaid = C.HoursPayed,
Start = E.Start,
End = E.End,
Time = E.End - E.Start
}).ToList();
JsonToSend.
//Not sure how to add each of these ClientInfo list items to the JsonToSend object
}
return new JsonResult { Data = JsonToSend, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
}
I want to be able to add each ClientInfo list to the JsonToSend Object and just send that, but looking online I cant find any syntax on how to do this. Any help or nudge in the right direction will be much appreciated!
Thanks in advance! :)
Edit:
Also tried:
List<JsonResult> bookings = new List<JsonResult>();
// var JsonToSend = new JsonResult();
foreach (var Company in ClientList)
{
var ClientInfo = (from E in dc.EventsAllLocations
join C in cleints.Clients on E.CompanyName equals C.Company
where C.Company == Company.ToString() && E.Start.Year == DateTime.Now.Year && E.Start.Month == DateTime.Now.Month
select new
{
Company = E.CompanyName,
Location = E.Location,
HoursPaid = C.HoursPayed,
Start = E.Start,
End = E.End,
Time = E.End - E.Start
}).ToList();
bookings.Add(ClientInfo);
//Not sure how to add each of these ClientInfo list items to the JsonToSend object
}
and getting the error
"Cannot convert from generic list to syste.web.mvc.JsonResult"
I usually convert the data into a List<> before returning it to the View, like below.
public JsonResult GetInfoToExport()
{
CleintEntities cleints = new CleintEntities();
var ClientList = cleints.Clients.ToList();
List<object> ReturnData = new List<object>();
foreach (var Company in ClientList)
{
ReturnData.Add(new { CompanyName = Company.Name, ID = Company.ID //
etc });
}
return Json(new { Data = ReturnData }, JsonRequestBehavior.AllowGet);
}
You can then access the JSON object data on the view like such:
<script type="text/javascript">
function GetClientData()
{
$.ajax({
url: '/Controller/GetInfoToExport,
dataType: 'json',
type: 'POST' // use POST to avoid IE caching JavaScript data
success: function (data)
{
for (var i = 0; i < data.Data.length; i++)
{
document.getElementById('someelement').innerHTML += '<label id="C' + data.Data[i].ID +'">' + data.Data[i].CompanyName + '</label><br>';
}
}});
}

jQuery Datatable: pagination and filter not display correctly

I dont know how to solve this, try a whole day but didn't success to fix the pagination. I'm using jQuery datatable, and to display my huge data, I'm using server side.
As a testing, only call 10 row of data to the table. Then before pass to table, I restructured the data inside dataSrc, using this solution . The table display successfully but the pagination and filter not display correctly.
Can anyone help this.
Below is my code.
AJAX
$('#example').DataTable({
"processing": true,
"serverSide": true,
"ajax": {
type: "POST",
contentType: "application/json; charset=utf-8",
url: "datatables.aspx/GetData",
'data': function (data) {
return JSON.stringify(data);
},
"dataSrc": function (data) {
var json = $.parseJSON(data.d);
var myData = {};
myData.draw = parseInt(json.otherData[0].draw);
myData.recordsTotal = parseInt(json.otherData[0].recordsTotal);
myData.recordsFiltered = parseInt(json.otherData[0].recordsFiltered);
myData.data = json.searchData;
return myData.data;
}
},
"columns": [
{ "data": "Username" }
]
}
});
C#
[WebMethod]
[ScriptMethod(UseHttpGet = false)]
public static string GetData(int draw, object columns, object order, int start, int length, object search)
{
string constr = ConfigurationManager.ConnectionStrings["DBConnection"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
string mySql = "SELECT TOP 10 username AS Username FROM user_lookup";
using (SqlCommand cmd = new SqlCommand(mySql, con))
{
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
con.Open();
DataSet ds = new DataSet();
sda.Fill(ds, "searchData");
DataTable newDT = new DataTable("otherData");
//Add columns to DataTable.
newDT.Columns.AddRange(new DataColumn[4] {
new DataColumn("draw"),
new DataColumn("recordsTotal"),
new DataColumn("recordsFiltered"),
new DataColumn("userRole")
});
//Add rows to DataTable.
newDT.Rows.Add(draw, length, start, "myrole");
ds.Tables.Add(newDT);
string JSONString = string.Empty;
JSONString = JsonConvert.SerializeObject(ds);
return JSONString;
}
}
}
}
This is the data I return back to datatable to structured the table.
Data filter and pagination not correct, should be only 1 page of pagination.
I have a solution for our case. You should modify the object of your response directly.
"dataSrc": function (data) {
var json = $.parseJSON(data.d);
data.draw = parseInt(json.otherData[0].draw);
data.recordsTotal = parseInt(json.otherData[0].recordsTotal);
data.recordsFiltered = parseInt(json.otherData[0].recordsFiltered);
data.data = json.searchData;
return data.data;
}
Hopefully, it works in your case.
Your response doesn't contain property otherData and searchData and you are accessing data by these names.
Your response is a simple object which has following properties.
data
recordsTotal
recordsFiltered
draw
So you need to access them directly from your response like this
var myData = {};
myData.draw = parseInt(json.draw);
myData.recordsTotal = parseInt(json.recordsTotal);
myData.recordsFiltered = parseInt(json.recordsFiltered);
myData.data = json.data;
Also recordsTotal is should be total number of records right now you are returning 10 and records shown are also 10.
You are getting NaN because there is no property json.otherData[0].recordsFiltered so when you will change it to json.recordsFiltered it will show numbers.

Grid.MVC use select fillter form list<T>

I'm a newbie in MVC. Iuse Grid.MVC to show a list. I'm trying to create custom fillter for string and date columns as [Demo1. I had read the document of Grid.MVC but it doesn't work. The select hasn't any option.
This is my script
<script>
function CustomersFilterWidget() {
/***
* This method must return type of registered widget type in 'SetFilterWidgetType' method
*/
this.getAssociatedTypes = function () {
return ["CustomCompanyNameFilterWidget"];
};
/***
* This method invokes when filter widget was shown on the page
*/
this.onShow = function () {
/* Place your on show logic here */
};
this.showClearFilterButton = function () {
return true;
};
/***
* This method will invoke when user was clicked on filter button.
* container - html element, which must contain widget layout;
* lang - current language settings;
* typeName - current column type (if widget assign to multipile types, see: getAssociatedTypes);
* values - current filter values. Array of objects [{filterValue: '', filterType:'1'}];
* cb - callback function that must invoked when user want to filter this column. Widget must pass filter type and filter value.
* data - widget data passed from the server
*/
this.onRender = function (container, lang, typeName, values, cb, data) {
//store parameters:
this.cb = cb;
this.container = container;
this.lang = lang;
//this filterwidget demo supports only 1 filter value for column column
this.value = values.length > 0 ? values[0] : { filterType: 1, filterValue: "" };
this.renderWidget(); //onRender filter widget
this.loadCustomers(); //load customer's list from the server
this.registerEvents(); //handle events
};
this.renderWidget = function () {
var html = '<p><i>This is custom filter widget demo.</i></p>\
<p>Select customer to filter:</p>\
<select style="width:250px;" class="grid-filter-type customerslist form-control">\
</select>';
this.container.append(html);
};
/***
* Method loads all customers from the server via Ajax:
*/
this.loadCustomers = function () {
var $this = this;
$.post("/QuanLySanPham/GetTenSach", function (data) {
$this.fillCustomers(data.Items);
});
};
/***
* Method fill customers select list by data
*/
this.fillCustomers = function (items) {
var customerList = this.container.find(".customerslist");
for (var i = 0; i < items.length; i++) {
alert(data);
customerList.append('<option ' + (items[i] == this.value.filterValue ? 'selected="selected"' : '') + ' value="' + items[i] + '">' + items[i] + '</option>');
}
};
/***
* Internal method that register event handlers for 'apply' button.
*/
this.registerEvents = function () {
//get list with customers
var customerList = this.container.find(".customerslist");
//save current context:
var $context = this;
//register onclick event handler
customerList.change(function () {
//invoke callback with selected filter values:
var values = [{ filterValue: $(this).val(), filterType: 1 /* Equals */ }];
$context.cb(values);
});
};
}
$(function () {
pageGrids.ordersGrid.addFilterWidget(new CustomersFilterWidget());
});
</script>
This is my Controller
QuanLyBanSachEntities db = new QuanLyBanSachEntities();
public ActionResult Index(int? page)
{
//int pageNumber = (page ?? 1);
//int pageSize = 10;
//return View(db.Saches.ToList().OrderBy(n => n.MaSach).ToPagedList(pageNumber, pageSize));
List<WebBanSach.Models.Sach> customerslist = db.Saches.ToList();
return View(customerslist);
}
public JsonResult GetTenSach()
{
List<string> customerslist = db.Saches.Select(s => s.TenSach).ToList();
return Json(customerslist, JsonRequestBehavior.AllowGet);
}
Could you give me an advice on how to fill this select tag?

How to set the display value and the value of autocompleted textbox?

I've made an auto-completion in a textbox using Jquery as follows:
$(document).ready(function () {
$('#searchCollabo').autocomplete({
source: '#Url.Action("AutocompleteCollabo")'
});
});
So the data come from the method AutocompleteCollabo which looks like that:
public ActionResult AutocompleteCollabo(string term)
{
int NumDossier = StructureData.DonneNumDossier((string)Session["NumCRPCEN"], (string)Session["MotDePasse"]);
List<Contact> ListeContacts = StructureData.DonneListeElementDossier(NumDossier);
Contact[] tabContacts = new Contact[ListeContacts.Count()];
int count = 0;
foreach (Contact contact in ListeContacts)
{
tabContacts[count] = contact;
count++;
}
var collaborateurs = tabContacts;
var collaborateurFiltres = collaborateurs.Where(
item => item.Nom.Contains(term) || item.Fonction.Contains(term)
);
return Json(collaborateurFiltres, JsonRequestBehavior.AllowGet);
}
The returned json contains a list of object as below:
[{"ListeFonctions":[],"IdContact":91264,"Nom":"solecki","Prenom":"hubert","Email":"hsolecki#mail.c"}]
Now I would like to set the display name (Name + function) and the value which I want to get when I select a row of the auto-completion. Do you have an Idea ?
I found out how to do it, it may help.
The function that I'm calling throught an Ajax call:
public ActionResult AutocompleteCollabo(string term)
{
int NumDossier = StructureData.DonneNumDossier((string)Session["NumCRPCEN"], (string)Session["MotDePasse"]);
List<Contact> ListeContacts = StructureData.DonneListeElementDossier(NumDossier);
var tabContactFull = ListeContacts.Where(contact => contact.Nom.Contains(term) || contact.Prenom.Contains(term) || contact.Fonction.Contains(term));
var tabInfosUtiles = tabContactFull.Select(contact => new { label = contact.Nom + " " + contact.Prenom + " ("+contact.Fonction+") ", value = contact.Nom + " " + contact.Prenom + " ("+contact.Fonction+") ", id = contact.IdContact }).ToArray();
// We set our needed informations with a title like "Label", "Value"
// So the auto-complete can find by itself which data to display and which are for the value
return Json(tabInfosUtiles, JsonRequestBehavior.AllowGet);
}
My Ajax call and the success event:
$(document).ready(function () {
$('#searchCollabo').autocomplete({
source: '#Url.Action("AutocompleteCollabo")',
select: function (event, ui) {
$("#idElement").val(ui.item.id);
// If you want to get the value : ui.item.Value
// If you want to get the label : ui.item.Label
}
});
});
Hope it helps some of you !

Google maps - show marker window from result list

code
//array store the markers
var googleMarker = [];
//this function get json object with the marker data
//place name,place id,place address.
function AjaxGetUserToPlaces(res)
{
var l = res.value.length;
for(var i=0;i<l;i++)
{
var point = new GLatLng(res.value[i].lng,res.value[i].lat)
map.addOverlay(createMarkerInfo(i,point,res.value[i].placeName,res.value[i].placeId));
polylineArray.push(point);
}
}
//the function create the openWindow for the marker.
function createMarkerInfo(i,latlng , placeName,placeId)
{
var marker = new GMarker(latlng);
marker.value = placeId;
GEvent.addListener(marker, 'click', function()
{
marker.openInfoWindowHtml(''+
'<a href='+baseUrl+'ui/pages/place/place.aspx?plid='+placeId+'>'+placeName+'</a>');
});
googleMarker[i] = marker
return marker;
}
//this function occur when user click on one of the result.
//it gets the number in the array googleMarker.
function showMarkerInfoWindow(i)
{
//here i want to open the marker info window.
//pay attention, i dont have the html to put inside the infowindow
//i want just to show the infowindoe with the exising html
//that created prevusly from the function createMarkerInfo
googleMarker[i].openInfoWindowHtml();
}
You can trigger a click event on the marker to open its info window:
GEvent.trigger(googleMarker[i], googleMarker[i].getLatLng());
EDITED: If you have the co-ordinates, you can pass the values to your createMarker() function directly.
Like this:
HTMLCODE:
List1
List2
List3
JS CODE:
function createMarker(x,y,msg) {
var point = new GLatLng(x,y);
var myHtml = msg;
var baseIcon = new GIcon();
baseIcon.shadow = "";
baseIcon.iconSize = new GSize(20, 34);
baseIcon.shadowSize = new GSize(37, 34);
baseIcon.iconAnchor = new GPoint(9, 34);
baseIcon.infoWindowAnchor = new GPoint(9, 2);
baseIcon.infoShadowAnchor = new GPoint(18, 25);
var letteredIcon = new GIcon(baseIcon);
letteredIcon.image = "http://www.google.com/intl/en_ALL/mapfiles/marker.png";
markerOptions = { icon:letteredIcon };
var marker = new GMarker(point,markerOptions);
GEvent.addListener(marker, "mouseover", function() {
map.openInfoWindowHtml(point, myHtml);
});
}
The Geocoder sample http://gmaps-samples-v3.googlecode.com/svn/trunk/geocoder/v3-geocoder-tool.html looks like just what you want to do (view source)

Categories

Resources