I am trying to create a chart (using CharJs.js) with multiple data sets and have it displayed in my MVC project.
The idea is to not have the datasets manually predefined and then access each one of it in my view. This has to be built dynamically based on how many objects I have in a list.
This is my Model:
[DataContract]
public class DataPoint : IDataPoint
{
public DataPoint(string label, double y)
{
this.Label = label;
this.Y = y;
}
//Explicitly setting the name to be used while serializing to JSON.
[DataMember(Name = "label")]
public string Label { get; set; }
//Explicitly setting the name to be used while serializing to JSON.
[DataMember(Name = "y")]
public Nullable<double> Y { get; set; }
//public List<double> Y { get; set; }
}
My Controller:
public async Task<ActionResult> ShowDetails(int ProductId, string PartId, string SupplierName, string fromSearchString, int? fromPage)
{
List<string> DbSupplierList = await _itScopeRepository.GetSupplierByPartId(Convert.ToInt32(PartId));
var ItScopeProduct = _itScopeRepository.GetProductById(ProductId);
ItScopeProduct.Supplier = SupplierName;
ItScopeProduct.SupplierList = DbSupplierList;
ViewBag.FromSearchString = fromSearchString;
ViewBag.FromPage = fromPage;
var obj = await CreateLineChart(DbSupplierList, PartId);
ItScopeProduct.DataPoints = obj;
return View("DetailsView", ItScopeProduct);
}
In my case here, the DataPoints is of type List<List<DataPoint>> and the list is being unfold in my View:
And this is my view:
<!DOCTYPE HTML>
<html>
<head>
<script src="~/Scripts/jquery-1.7.1.js"></script>
<script type="text/javascript">
window.onload = function () {
var dataSecond = {
type: "line",
name:'#Html.Raw(JsonConvert.SerializeObject(Model.Supplier))',
showInLegend: true,
dataPoints: #Html.Raw(JsonConvert.SerializeObject(Model.DataPoints[0]))
};
var dataSecond2 = {
type: "line",
name:"Dexxit",
showInLegend: true,
dataPoints: #Html.Raw(JsonConvert.SerializeObject(Model.DataPoints[1]))
};
var chart = new CanvasJS.Chart("chartContainer", {
animationEnabled: true,
title: {
text: "Product price history"
},
axisY: {
includeZero: false
},
toolTip: {
shared: true
},
data: [dataSecond, dataSecond2]
});
chart.render();
}
</script>
</head>
<body>
<div id="chartContainer" style="height: 370px; width: 100%;"></div>
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
</body>
</html>
As you can see, right now I am taking each Object from the list manually and I would like to have it integrated in a loop where it creates an array of objects which will then be passed to my chart dataset.
I have tried something like this:
var testing;
var listOfDataPoints = [];
for(var i = 0; i < #Model.DataPoints.Count; i++){
testing = {
type: "line",
name: '#Html.Raw(JsonConvert.SerializeObject(Model.Supplier))',
showInLegend: true,
dataPoints: #Html.Raw(JsonConvert.SerializeObject(Model.DataPoints[i]))
};
listOfDataPoints.push(testing);
}
But unfortunately I cannot pass a javascript int value to my C# model, therefore making this solution unusable.
Now my question is: Is it possible to loop through my List of objects and create n amount (base on how many items are in my list)of javascript objects and have them inserted into an array?
The js obj should have the following structure:
var myDataset = {
type: "line",
name: '#Html.Raw(JsonConvert.SerializeObject(Model.Supplier))',
showInLegend: true,
dataPoints: #Html.Raw(JsonConvert.SerializeObject(Model.DataPoints[i]))
}
Ps. I am not very experienced with javascript, reason for why I am reaching for some guidance since I haven't found anything similar to what I need.
EDIT
I have tried the other way around: Having a c# loop and execute a javascript function where i am creating my objects.
var yest = [];
var listOfPoints = [];
function addMarker(supplier, datapo)
{
yest = {
type: "line",
name: "Dexxit",
showInLegend: true,
dataPoints: datapo
};
listOfPoints.push(yest);
}
#for(int i = 0; i < Model.DataPoints.Count; i++)
{
#:addMarker('#Html.Raw(JsonConvert.SerializeObject(Model.Supplier))', #Html.Raw(JsonConvert.SerializeObject(Model.DataPoints[i])));
}
But when i am assigning listOfPoints to my dataset, it shows an empty chart. Any ideas why?
Manage to find a working solution based on my last edit:
Had some small changes on my Controller and that was to change one of my Model (the one passed to my View) functions from List<List<DataPoint>> DataPoints {get;set;} to `List>> DataPoint{get;set;}
My new Controller:
public async Task<ActionResult> ShowDetails(int ProductId, string PartId, string SupplierName, string fromSearchString, int? fromPage)
{
List<string> DbSupplierList = await _itScopeRepository.GetSupplierByPartId(Convert.ToInt32(PartId));
var ItScopeProduct = _itScopeRepository.GetProductById(ProductId);
ItScopeProduct.Supplier = SupplierName;
ItScopeProduct.SupplierList = DbSupplierList;
ViewBag.FromSearchString = fromSearchString;
ViewBag.FromPage = fromPage;
var obj = await CreateLineChart(DbSupplierList, PartId);
List<KeyValuePair<string, List<IDataPoint>>> ConvertToInterface = new List<KeyValuePair<string, List<IDataPoint>>>();
foreach (var item in obj)
{
ConvertToInterface.Add(new KeyValuePair<string, List<IDataPoint>>(item.Key, item.Value.ToList<IDataPoint>()));
}
ItScopeProduct.DataPoints = ConvertToInterface;
return View("DetailsView", ItScopeProduct);
}
Updated View:
<!DOCTYPE HTML>
<html>
<head>
<script src="~/Scripts/jquery-1.7.1.js"></script>
<script type="text/javascript">
window.onload = function () {
var listOfDataPoints = [];
var MyObj;
function addMarker(supplier, datapo)
{
var yest = {
type: "line",
name: supplier,
showInLegend: true,
dataPoints: datapo
};
return yest;
}
#for(int i = 0; i < Model.DataPoints.Count; i++)
{
#:MyObj = addMarker('#Html.Raw(JsonConvert.SerializeObject(Model.DataPoints[i].Key))', #Html.Raw(JsonConvert.SerializeObject(Model.DataPoints[i].Value)));
#:listOfDataPoints.push(MyObj);
}
var chart = new CanvasJS.Chart("chartContainer", {
animationEnabled: true,
title: {
text: "Product price history"
},
axisY: {
includeZero: false
},
toolTip: {
shared: true
},
data: listOfDataPoints
});
chart.render();
}
</script>
</head>
<body>
<div id="chartContainer" style="height: 370px; width: 100%;"></div>
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
</body>
</html>
My chart is now dynamically built and it can show data based on what is in my Model.DataPoints.
I hope this can be of some help for someone in the same position.
Related
I have a view where I am trying to implement the auto populate the text box/drop down field. I am using a list which I query on.
I am following this example http://www.dotnetqueries.com/Article/159/how-to-implement-select2-with-ajax-and-json-in-asp-net-mvc , break point does not even hit the method in my controller. so is there something wrong with the way I set this up or the way the action result method is called in controller.
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using TestSelect2.Models;
using Controller = Microsoft.AspNetCore.Mvc.Controller;
namespace TestSelect2.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
return View();
}
[Microsoft.AspNetCore.Mvc.HttpPost]
[Microsoft.AspNetCore.Mvc.Route("/home/account-list")]
public Microsoft.AspNetCore.Mvc.ActionResult GetAccounts(string q)
{
List<Account> accounts = new List<Account>();
// Add parts to the list.
accounts.Add(new Account() { Id = 1, AccountNumber = "MVP1" });
accounts.Add(new Account() { Id = 1, AccountNumber = "MVP11" });
accounts.Add(new Account() { Id = 1, AccountNumber = "ABC2" });
accounts.Add(new Account() { Id = 1, AccountNumber = "ABC3" });
accounts.Add(new Account() { Id = 1, AccountNumber = "XYZ3" });
accounts.Add(new Account() { Id = 1, AccountNumber = "XYZ4" });
if (!(string.IsNullOrEmpty(q) || string.IsNullOrWhiteSpace(q)))
{
accounts = accounts.Where(x => x.AccountNumber.ToLower().StartsWith(q.ToLower())).ToList();
}
return Json(new { items = accounts }, JsonRequestBehavior.AllowGet);
}
}
}
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Select2 DEMO</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
<script>
$(document).ready(function () {
$(".accountSelect").select2({
ajax: {
url: '/home/account-list',
width: 'resolve',
data: function (params) {
return {
q: params.term// search term
};
},
processResults: function (data) {
return {
results: data.items
};
},
minimumInputLength: 2,
width: 'resolve'
}
});
});
</script>
<style>
body {
margin: auto;
width: 600px;
padding: 50px;
}
.accountSelect {
width: 400px;
}
</style>
</head>
<body>
<form method="post">
<select class="accountSelect"></select>
</form>
</body>
</html>
Remove the [HttpPost] attribute on GetAccounts action. Since the ajax makes a get request.And the tutorial you follow is for asp.net but not asp.net core, there is no JsonRequestBehavior.
Note: select2model must with id and text two properties, otherwise, it can't be recognized. Change your Account model like below:
public class Account
{
public int Id { get; set; }
public string Text { get; set; }
}
And the controller action, make sure the id can't be the same.
[Route("/home/account-list")]
public IActionResult GetAccounts(string q)
{
List<Account> accounts = new List<Account>();
// Add parts to the list.
accounts.Add(new Account() { Id = 1, Text = "MVP1" });
accounts.Add(new Account() { Id = 2, Text = "MVP11" });
accounts.Add(new Account() { Id = 3, Text = "ABC2" });
accounts.Add(new Account() { Id = 4, Text = "ABC3" });
accounts.Add(new Account() { Id = 5, Text = "XYZ3" });
accounts.Add(new Account() { Id = 6, Text = "XYZ4" });
if (!(string.IsNullOrEmpty(q) || string.IsNullOrWhiteSpace(q)))
{
accounts = accounts.Where(x => x.Text.ToLower().StartsWith(q.ToLower())).ToList();
}
return Json(new { items = accounts });
}
View and Scripts:
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Select2 DEMO</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
<script>
$(document).ready(function () {
$(".accountSelect").select2({
minimumInputLength: 2,
ajax: {
url: '/home/account-list',
data: function (params) {
return {
q: params.term// search term
};
},
processResults: function (data) {
return {
results: data.items
}
},
}
});
});
</script>
<style>
body {
margin: auto;
width: 600px;
padding: 50px;
}
.accountSelect {
width: 400px;
}
</style>
</head>
<body>
<form method="post">
<select class="accountSelect"></select>
</form>
</body>
</html>
Result:
You may try as below:
//1. Action Method Which Returns the data.
public ActionResult GetSelect2Data(string query)
{
//In Realtime This should come from the Database
List<DropDownItem> collection = new List<DropDownItem>() {
new DropDownItem(){ Value = 1, Text = "Switzerland"},
new DropDownItem(){ Value = 2, Text = "Canada"},
new DropDownItem(){ Value = 3, Text = "Japan"},
new DropDownItem(){ Value = 4, Text = "Germany"},
new DropDownItem(){ Value = 5, Text = "Australia"},
new DropDownItem(){ Value = 6, Text = "United Kingdom"},
new DropDownItem(){ Value = 7, Text = "United States"},
new DropDownItem(){ Value = 8, Text = "Sweden"},
new DropDownItem(){ Value = 9, Text = "India"},
new DropDownItem(){ Value = 10, Text = "Russia"},
};
var searchResult = from c in collection
where c.Text.Contains(query,
StringComparison.CurrentCultureIgnoreCase)
select c;
return Json(searchResult.ToList());
}
///2. JS Method which binds any HTML Select as Select2 or Smart Select.
///In the User Interface (.cshtml file)You may define a framework JS Function as which could be used anywhere
function registerSelect2(dropDownSelector, ajaxUrl) {
$(dropDownSelector).select2({
ajax: {
url: ajaxUrl,
dataType: 'json',
delay: 10,
type: 'GET',
data: function (params) {
return {
query: params.term, // search term
};
}
, processResults: function (data) {
return {
results: $.map(data, function (item) {
return {
id: item.value,
text: item.text,
};
})
};
},
cache: true,
},
minimumInputLength: 3,
allowHtml: true,
allowClear: true
});
}
//3. Invoke the JS Function to make any particular Select a Select2.
$(function () {
//Just you need to pass the Selector of your control and the Ajax Url from which data has to be loaded
registerSelect2("#ddlSelect2", "/user/GetSelect2Data");
});
//This is the Simple Select which's made a Select2 Control. Paste it somewhere in the UI
<select id="ddlSelect2"></select>
I'm trying to use high charts via angular to take advantage of double binding. I'm having an issue rendering the data, the graph works but the data is not showing up in the chart. When I check the DOM console I can get the array but for some reason its not showing up in the graph.
cpvmPartners = [];
cpvmPlannedCpm = [];
actualCpm = [];
graphData = [];
cpvm = [];
plannedPrepared = [];
getData = function(){
$.getJSON('/cpvmdata', function(data) {
for(k in data){
if(data[k]['audience'] == 'GCM'){
graphData.push([data[k]['partner'],data[k]['plannedcpm']])
actualCpm.push(Math.round((data[k]['mediacost']/data[k]['impressions']*1000)))
cpvmPlannedCpm.push(data[k]['plannedcpm'])
cpvmPartners.push(data[k]['partner'])
}
}
});
}
prepareData = function(){
for(var i = 0; i < actualCpm.length; i++) {
actualPrepared.push({name: "CPM", data: actualCpm[i]})
plannedPrepared.push({name: "Planned CPM", data: cpvmPlannedCpm[i]})
}
}
myApp = angular.module('main', ['highcharts-ng']);
myApp.controller('graphController', function ($scope) {
getData();
prepareData();
$scope.highchartsNG = {
options: {
chart: {
type: 'bar'
}
},
series: [{
data: actualCpm
}],
title: {
text: 'Hello'
},
loading: false
}
});
So the getData() function you call in the angular controller is asynchronous:
By the time you have gotten the data, you have already made your chart in $scope.highChartNg
That is why you can see your data the console but you don't actually set it to the actualCpm by the time angular is done. To fix this you need to create the chart IN your $.getJSON function like so:
var options = {
chart: {
renderTo: 'container',
type: 'spline'
},
series: [{}]
};
$.getJSON('data.json', function(data) {
options.series[0].data = data;
var chart = new Highcharts.Chart(options);
});
You can see more here: http://www.highcharts.com/docs/working-with-data/custom-preprocessing
Easier just to use
$http.get
Angular service.
Blending jQuery and Angular is troublesome for scoping.
$http.get('cpvmdata')
.then(function(response){
$scope.output = response.data;
for(k in $scope.output){
if($scope.output[k]['audience'] == 'GCM'){
$scope.planned.push($scope.output[k]['plannedcpm'])
$scope.partners.push($scope.output[k]['partner'])
$scope.cpm.push(Math.round(($scope.output[k]['mediacost']/$scope.output[k]['impressions']*1000)))
}
}
});
Ok, here are the Versions:
Kendo UI v2014.3.1119
AngularJS v1.3.6
jQuery v#1.8.1 jquery.com
The issue is the following: I have a kendo upload that should populate a grid after a excel file is read. I'm using Kendo UI Angular Directives. Here are some key pieces of code:
Upload Html
<input name="files"
type="file"
kendo-upload
k-async="{ saveUrl: '{{dialogOptions.ImportUrl}}', autoUpload: false, batch: true }"
k-options="{localization: {uploadSelectedFiles: '{{messages.Global_Button_Import}}'}}"
k-error="onImportError"
k-select="onSelect"
k-success="onImportSuccess" k-multiple="false" />
Grid Html
<div kendo-grid="grid" k-options="gridOptions" k-ng-delay="gridOptions" k-rebind="gridOptions" >
</div>
Key pieces on the controller
angular.module('global').controller('ImportResultsController', [
'$scope', 'BaseApi', 'ImportResultsService', 'GridUtil', '$http', '$q', '$timeout',
function ($scope, BaseApi, ImportResultsService, GridUtil, $http, $q, $timeout) {
$scope.gridOptions;
$scope.gridColumns;
$scope.results = new kendo.data.ObservableArray([]);
//These columns should come from the server, right now are harcoded
$scope.getGridColumns = function () {
$scope.gridColumns = [
{ field: "Zone", width: 70, title: "Zone", template: "" },
{ field: "Aisle", width: 70, title: "Aisle", template: "" },
{ field: "Rack", width: 70, title: "Rack", template: "" },
{ field: "Shelf", width: 70, title: "Shelf", template: "" },
{ field: "Bin", width: 70, title: "Bin", template: "" },
//{ field: "DateEffectiveFrom", width: 70, title: "Date" },
{ field: "BinStatus", width: 70, title: "BinStatus", template: "" }
];
}
$scope.getClientGridOptions = function(columns, data, pageSize) {
var gridOptions = {
sortable: true,
dataSource: {
data: data,
pageSize: pageSize
},
selectable: 'row',
columns: columns,
pageable: {
pageSize: pageSize,
refresh: false,
pageSizes: [10, 20, 30],
messages: $.kendoMessages
},
};
return gridOptions
}
$scope.onImportSuccess = function (e) {
var files = e.files;
if (e.operation == "upload") {
console.log(files);
if (e.XMLHttpRequest.response != "") {
var model = $.parseJSON(e.XMLHttpRequest.response); //This step does not fail, model return is always filled
$scope.results = new kendo.data.ObservableArray([]);
for (var i = 0; i < model.Data.length; i++) {
$scope.results.push(model.Data[i]);
}
$scope.gridOptions = $scope.getClientGridOptions($scope.gridColumns, $scope.results, 10);
//$scope.grid.dataSource.data($scope.results); //This does not work
$scope.isDataReady = true;
// $("#grid").data("kendoGrid").dataSource.data($scope.results) //This does not work
// $scope.grid.refresh(); //This does not work
$scope.$apply()
}
}
}
}]);
The issues vary. Sometimes I get the data bound until the second uploaded file, and after the third time, I start receiving 'Cannot read property 'get' of undefined ' errors. When this second error happens, the bind works, but the error is present. Do you have any idea of what could it be?
In case of you need the url for the upload, here's the method. Is an MVC .net application. Since I always get the response correctly and it's a Json Array, I believe there's no issue there, but here's anyways.
dialogOptions.ImportUrl = LoadImportedBinLocations
MVC Controller
[System.Web.Http.HttpPost]
public ActionResult LoadImportedBinLocations(IEnumerable<HttpPostedFileBase> files)
{
bool success = false;
var importHistory = new PartsImportHistory();
List<dynamic> data = null;
try
{
//int divisor = 0;
//var y = 5 / divisor;
if (files != null)
{
using (var client = new ServiceLocator<IPartsService>())
{
foreach (var file in files)
{
string extension = Path.GetExtension(file.FileName);
bool isExcelFile = extension == ".xls" || extension == ".xlsx";
if (isExcelFile)
{
var filePath = UploadAttachment(file);
//importHistory = client.Service.SavePartsImportHistory(new PartsImportHistory
//{
// CreatedByName = CurrentContext.UserDisplayName,
// CreatedByUserID = CurrentContext.UserId,
// PartsImportStatus = (int)DMSModel.EnumStore.PartsImportStatus.InProgress,
// FilePath = filePath
//});
data = new List<dynamic>
{
new { Zone = "A", Aisle = "02", Rack = "06", Shelf = "20", Bin = "D", DateEffectiveFrom = DateTime.UtcNow, BinStatus = "Unblocked", IsValid= true, ImportError ="" },
new { Zone = "B", Aisle = "02", Rack = "06", Shelf = "10", Bin = "D", DateEffectiveFrom = DateTime.UtcNow, BinStatus = "Blocked", IsValid=false, ImportError="Zone does not Exist" }
};
success = true;
}
else
{
throw new Exception(WarpDMS.Globalization.Resources.PartsAdmin_ImportParts_ErrorFileFormat);
}
}
}
}
return Json(new { success = success, Data = data });
}
catch (Exception ex)
{
return Content(ex.Message ?? ex.ToString());
}
}
private string UploadAttachment(HttpPostedFileBase item)
{
string path = string.Empty;
string internalFileName = string.Empty;
string basePath = ConfigManager.ATTACHMENTS_PATH;
if (item != null && item.ContentLength > 0)
{
internalFileName = System.IO.Path.ChangeExtension(Guid.NewGuid().ToString(), System.IO.Path.GetExtension(item.FileName));
path = Path.Combine(basePath, internalFileName);
item.SaveAs(path);
}
return Path.Combine(basePath, internalFileName).Replace('\\', '/');
}
I am trying to convert a C# list object to the correct format for a Flot Bar chart. For some reason I just can't seem to get it done correctly. I have tried several different methods. The JSON I am returning is valid JSON and the list is valid but for some reason the Flot chart wants the data in a different format. Any help would be appreciated. Thank you!
Here is the converted C# List to JSON Array
[{"color":"red","data":["Agriculture",0,2]},{"color":"red","data":["Healthcare",0,1]},{"color":"red","data":["Manufacturing",0,0]},{"color":"red","data":["Retail",0,0]},{"color":"red","data":["Information Technology",0,0]}]
I use this method to do so:
$.ajax({
type: "POST",
url: "Summary.asmx/getBarChartSeriesData",
data: JSON.stringify({ userid: userid }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
barSummaryData = response.d;
var jsonArray = JSON.parse(response.d);
//this format seems to work
//var data = [{ data: [[0, 1]], color: "red" }, { data: [[1, 2]], color: "yellow" }, { data: [[2, 3]], color: "green" }];
var plot =
$.plot($('#barSummaryPlaceholder'), jsonArray, {
series: {
bars: {
show: true,
barWidth: 0.3,
align: "center"
}
},
xaxis: {
ticks: ticks
},
grid: { hoverable: true, clickable: true }
});
},
failure: function (msg) {
$('#barSummaryPlaceholder').text(msg);
}
});
Here is the C# Method in the ASMX:
public string getSummaryBarChartSeriesData(int userid)
{
List<Series> SeriesData = new List<Series>();
DataTable dt = new DataTable();
dt.Clear();
dt = chartcode.RetrieveSummaryBarChartData(userid);
int countOfRows = 0;
foreach (DataRow row in dt.Rows)
{
List<object> objData = new List<object>();
objData.Add(row["Name"].ToString());
objData.Add(countOfRows);
objData.Add(Convert.ToInt32(row["CountOfStudents"]));
SeriesData.Add(
new CareerClusterSeries
{
data = objData,
color = "red"
});
}
var jsonSerialiser = new JavaScriptSerializer();
var json = jsonSerialiser.Serialize(SeriesData);
return json;
}
For some reason the C# json string is in the valid format for JSON itself but NOT the correct format for Flot charts which is the chart system I am trying to use.
First, from the documentation Flot Reference: Data Format, the data field should be an array of arrays of numbers, e.g.:
{
label: "y = 3",
data: [[0, 3], [10, 3]]
}
In contrast, you have an flat array of numbers with a string mixed in: {"data":["Agriculture",0,2], "color":"red",}. What is the purpose of the string -- is it the series label?
Next, did you forget to increment countOfRows? It's always zero in your code.
Assuming you wanted to increment the count and set row["Name"] to be the series label, the following should produce JSON that complies with the API:
public class Series
{
public string color { get; set; }
public List<IList<double>> data { get; set; }
public string label { get; set; }
}
And then:
public string getSummaryBarChartSeriesData(int userid)
{
var SeriesData = new List<Series>();
DataTable dt = chartcode.RetrieveSummaryBarChartData(userid);
int countOfRows = 0;
foreach (DataRow row in dt.Rows)
{
var rawData = new List<IList<double>>();
rawData.Add(new double[] { countOfRows++, Convert.ToInt32(row["CountOfStudents"]) });
//objData.Add(row["Name"].ToString());
SeriesData.Add(
new CareerClusterSeries
{
data = rawData,
color = "red",
label = row["Name"].ToString(), // Guessing you wanted this.
});
}
var jsonSerialiser = new JavaScriptSerializer();
var json = jsonSerialiser.Serialize(SeriesData);
return json;
}
I am using Jquery-JTable in my website to load details in a grid view and to let user be able to modify, delete app accordingly.
I am loading data successfully from 2 tables and then display them in my div. Now the user would like to modify a record accordingly to his/her wish.
I would like to let the user choose from a dropdown list obtained from another table. Can this be done?
Code Below: As you can see I am loading data from multiple tables using InnerJoin. For example I would like to let the user choose another Category or Language etc.
$queryString = "SELECT `app_id`,`app_name`,`app_type`,`app_url`,`AppAccepted`,`BenefitApp`, application_ageGroup.ageGroup,application_category.category, application_Country.country,application_Language.language FROM application INNER JOIN application_ageGroup ON application.ageGroup_id = application_ageGroup.ageGroup_id INNER JOIN application_category ON application.Category = application_category.category_id INNER JOIN application_Country ON application.country_id = application_Country.country_id INNER JOIN application_Language ON application.language_id = application_Language.language_id ORDER BY $jtSorting LIMIT $jtStartIndex,$jtPageSize";
Regards,
Make the Category column as dropdown and bind it with your query dataset :
$('#Table').jtable({
paging: true,
pageSize: 200,
sorting: true,
defaultSorting: 'Category ASC',
selecting: false,
multiselect: false,
selectingCheckboxes: false,
actions: {
listAction: '/Application/GetData',
updateAction: '/Application/EditData'
},
fields: {
Category: {
title: 'Category',
width: '10%',
list: false,
sorting: true,
options: '/Application/GetCategories'
}
});
In your controller action, fetch Category lists:
[HttpPost]
public JsonResult GetCategories()
{
try
{
DataTable dtCategories = new DataTable();
string query = "SELECT .....";
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
using (SqlCommand command = new SqlCommand(query, connection))
{
connection.Open();
dtCategories.Load(command.ExecuteReader());
}
List<Store> categoryList = DatatableToGenericList(dtCategories);
var categories = categoryList.Select(category => new { DisplayText = category.Name , Value = category.Id }).OrderBy(s => s.DisplayText);
return Json(new { Result = "OK", Options = categories });
}
catch (Exception ex)
{
return Json(new { Result = "ERROR", Message = ex.Message });
}
}
private static List<Store> DatatableToGenericList(DataTable table)
{
var categoryList = new List<Category>(table.Rows.Count);
foreach (DataRow row in table.Rows)
{
var values = row.ItemArray;
var store = new Category()
{
Id = values[0].ToString(),
Name = values[1].ToString()
};
categoryList.Add(store);
}
return categoryList;
}
Category Model
public class Category
{
public string Id { get; set; }
[Required]
public string Name { get; set; }
}
Hope this helps..