I am trying to add a new object to a existing JSON array. This is my JSON array stored in the database.
{
"Id":4,
"UserId":2336276,
"Name":"Data",
"Widgets":[
{
"Id":1,
"Description":"Test1",
"DataSource":"Person1",
"ChartType":"bar",
"x":0,
"y":0,
"width":3,
"height":2
},
{
"Id":2,
"Description":"Test2",
"DataSource":"Person2",
"ChartType":"pie",
"x":3,
"y":0,
"width":3,
"height":2
},
{
"Id":3,
"Description":"Test3",
"DataSource":"Person3",
"ChartType":"heatmap",
"x":6,
"y":0,
"width":3,
"height":2
}
]
}
When I want to add a new widget I want it as a object in this JSON array.
This is my Angular HTTP call:
$scope.addWidget = function () {
var Indata = {
"Id": $scope.widgets.Widgets.length + 1,
"name": $scope.name,
"description": $scope.Widgets.description,
"datasource": $scope.Widgets.datasource,
"charttype": $scope.Widgets.charttype,
"x": $scope.Widgets.x = 0,
"y": $scope.Widgets.y = 0,
"width": $scope.Widgets.width = 3,
"height": $scope.Widgets.height = 2
};
$http({
url: "Dashboard/AddWidget",
method: "POST",
params: Indata
})
$scope.widgets.push(Indata);
};
And this is my HTML page:
<md-dialog>
<form ng-cloak>
<md-toolbar>
<div class="md-toolbar-tools">
<h2>New widget</h2>
<span flex></span>
</div>
</md-toolbar>
<md-input-container>
<label>Name</label>
<input type="text" ng-model="name">
</md-input-container>
<md-dialog-content>
<label>Datasource</label>
<md-select ng-model="datasource"></md-select>
</md-dialog-content>
<md-dialog-content>
<label>Type graph</label>
<md-select ng-model="graphtype"></md-select>
</md-dialog-content>
<md-input-container>
<label>Description</label>
<input type="text" ng-model="description">
</md-input-container>
<md-dialog-actions layout="row">
<md-button id="add" ng-click="addWidget()">
Add widget
</md-button>
<md-button ng-click="hide()">
Cancel
</md-button>
</md-dialog-actions>
</form>
When I click on Addwidget it doesn't add to the JSON array but outside of it as a new object. I am not sure but I think I am doing something wrong with the nested json array.
What am I doing wrong?
Kind regards
UPDATE:
[HttpPost]
public string AddWidget(Dashboard model)
{
var data = _dashboarBusiness.StoreDashboard(model);
return Newtonsoft.Json.JsonConvert.SerializeObject(data);
}
You are not adding it into the json object that you obtained from database.
Suppose
$scope.jsonObj= {
"Id":4,
"UserId":2336276,
"Name":"Data",
"Widgets":[
{
"Id":1,
"Description":"Test1",
"DataSource":"Person1",
"ChartType":"bar",
"x":0,
"y":0,
"width":3,
"height":2
},
{
"Id":2,
"Description":"Test2",
"DataSource":"Person2",
"ChartType":"pie",
"x":3,
"y":0,
"width":3,
"height":2
},
{
"Id":3,
"Description":"Test3",
"DataSource":"Person3",
"ChartType":"heatmap",
"x":6,
"y":0,
"width":3,
"height":2
}
]
}
Then you have to push into the widgets array of this object.
$scope.jsonObj.Widgets.push(Indata);
You may also want to check if your $http is working correctly because I can't see anything being done in the success callback of the request.
$http({
url: "Dashboard/AddWidget",
method: "POST",
params: Indata
}).then(function(data) {
$scope.success = "Widgets added Successfully"
});
For more reference on $http, check https://docs.angularjs.org/api/ng/service/$http
Related
Recently I posted on Hight Charts where I did like to create dynamic charts based on Razor view loop. Here's the link - Dynamic Chart
I tried one of the solution provided by a SO user as follows:
<script>
async function createChart(containerName, dryArgument, operatingArgument){
let dryData = await fech(dryArgument)
let operatingData = await fech(operatingArgument)
Highcharts.chart(containerName, {
chart: {
type: 'column'
},
title: {
text: 'Monthly Average Rainfall'
},
subtitle: {
text: 'Source: WorldClimate.com'
},
xAxis: {
categories: [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec'
],
crosshair: true
},
yAxis: {
min: 0,
title: {
text: 'Rainfall (mm)'
}
},
tooltip: {
headerFormat: '<span style="font-size:10px">{point.key}</span><table>',
pointFormat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' +
'<td style="padding:0"><b>{point.y:.1f} mm</b></td></tr>',
footerFormat: '</table>',
shared: true,
useHTML: true
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
}
},
series: [
{
name: 'Dry',
data: JSON.parse(dryData)
}, {
name: 'Operating',
data: JSON.parse(operatingData)
}]
});
}
</script>
In the front-end, used this:
<div class="container-fluid">
<div class="row">
<div class="col-sm-12 col-lg-12 col-md-12 col-xs-12">
//Dynamic Chart - Starts
#if (Model.aLstTopsideModuleGroupBy.ToList().Count > 0)
{
foreach (var item in Model.aLstTopsideModuleGroupBy)
{
foreach (var item2 in item)
{
int i = 0;
<div id="container#i"></div>
<p class="highcharts-description">
</p>
<script>
window.onload = function () {
createChart('#container#i',#item2.BaseDry,#item2.BaseOp);
};
</script>
i++;
}
}
}
//Dynamic Chart - Ends
</div>
</div>
</div>
I am not sure if this is the correct way to do it, but got the following exception while trying:
Uncaught SyntaxError: missing ) after argument list
Is there any way to resolve the exception? I know, am doing something doing wrong here, any idea or suggestion would be appreciated.
Update 1: Exception
You don't have your Java Script correctly set up.
First of all, fetch() does return a promise that will give you a response object once fulfilled. That response object has json() function returning a promise that will return the json as JavaScript object once fulfilled. Promises are best awaited. The start of your createChart function should look this:
async function createChart(containerName, dryArgument, operatingArgument){
let dryData = await fetch(dryArgument) /* note you have a typo in your question */
let dryJson = await dryData.json();
let operatingData = await fetch(operatingArgument)
let operatingJson = await operatingData.json();
/* rest of code here */
In the series setup of HighCharts you now need to make these changes:
series: [
{
name: 'Dry',
data: dryJson
}, {
name: 'Operating',
data: operatingJson
}]
This does assume that dryJson and operatingJson are single dimension javascript arrays with numbers in it (so [1,2,3] will work, ['1', '2', '3'] doesn't nor does {items:[{score:1}]}.
The exact setup in the Razor page is a task I leave at you, it shouldn't be that hard to verify if the outcome of the rendered page matches the actual need.
For testing purposes I created stack snippet where I use posts and users from the Stack API as Json sources. As those are a slightly different shape you see a map over its items array to get the desired array of numbers:
async function createChart(containerName, dryArgument, operatingArgument){
let dryData = await fetch(dryArgument)
let dryJson = await dryData.json();
let operatingData = await fetch(operatingArgument)
let operatingJson = await operatingData.json();
Highcharts.chart(containerName, {
chart: {
type: 'column'
},
title: {
text: 'Monthly Average Rainfall'
},
subtitle: {
text: 'Source: WorldClimate.com'
},
xAxis: {
categories: [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec'
],
crosshair: true
},
yAxis: {
min: 0,
title: {
text: 'Rainfall (mm)'
}
},
tooltip: {
headerFormat: '<span style="font-size:10px">{point.key}</span><table>',
pointFormat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' +
'<td style="padding:0"><b>{point.y:.1f} mm</b></td></tr>',
footerFormat: '</table>',
shared: true,
useHTML: true
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
}
},
series: [
{
name: 'Dry',
data: dryJson.items.map(i => i.score)
}, {
name: 'Operating',
data: operatingJson.items.map(i => i.reputation / 100)
}]
});
}
async function start() {
var key = '1*tsYg4Q3UbK06qftc8VmQ(('
await createChart('container1', 'https://api.stackexchange.com/2.3/posts?order=desc&sort=votes&pagesize=12&site=stackoverflow&key='+key, 'https://api.stackexchange.com/2.3/users?order=desc&sort=reputation&pagesize=12&site=stackoverflow&key='+key)
}
start()
<script src="https://cdnjs.cloudflare.com/ajax/libs/highcharts/10.3.3/highcharts.js"></script>
<div id="container1">
loading ...
</div>
I am using ASP.NET; I am getting the data from the backend as expected, but it is not showing in the web page using a datatable.
Web page:
#{
ViewBag.Title = "Employee";
}
<h2>Employee List</h2>
<table id="myTable">
<thead>
<tr>
<th>EmployeeId</th>
<th>Name</th>
<th>Age</th>
<th>Position</th>
</tr>
</thead>
</table>
JavaScript portion of code (jQuery)
$(document).ready(function () {
$('#myTable').DataTable({
processing:true,
"ajax": {
"url": "/Employee/GetList",
"type": "GET",
"dataType": "json",
"success": function (msg) {
console.log(msg.data);
},
"failure": function (response) {
alert(response);
},
"error": function (response) {
alert(response);
}
},
"columns": [
{ data: "EmployeeId" },
{ data: "Name" },
{ data: "Age" },
{ data: "Position"},
]
});
});
Here is the response I am getting from the backend. This is the data I copied from Netword -> Response tab against the endpoint I call to fetch the data
{
"data": [
{
"EmployeeId": 1,
"Name": "Dhruv",
"Age": 23,
"Position": "Full Stack Developer"
},
{
"EmployeeId": 2,
"Name": "Soni",
"Age": 21,
"Position": "DBA"
},
{
"EmployeeId": 3,
"Name": "Mike",
"Age": 24,
"Position": "Frontend Developer"
},
{
"EmployeeId": 4,
"Name": "Bob",
"Age": 20,
"Position":"SRE"
}
]
}
I am trying to get the data from database and show it to the user using a datatable. I am successfully getting the response back from the database, but the data is not showing inside the table. And I can't figure it out why....
Update:3
Controller:
public ActionResult GetList()
{
var empList = new List<Employee>()
{
new Employee(){ EmployeeId = 1, Name = "A", Age = 19, Position = "Engineer-I"},
new Employee(){ EmployeeId = 2, Name = "B", Age = 20, Position = "Engineer-II"},
new Employee(){ EmployeeId = 3, Name = "C", Age = 21, Position = "Engineer-I"},
new Employee(){ EmployeeId = 4, Name = "D", Age = 22, Position = "Engineer-III"},
};
return Json(new { data = empList }, JsonRequestBehavior.AllowGet);
}
Note: You even can directly return Json(new { empList }) in that case, in your HTML-Ajax you only have to write return msg; not msg.data
View:
<h2>Employee List</h2>
<table id="myTable">
<thead>
<tr>
<th>EmployeeId</th>
<th>Name</th>
<th>Age</th>
<th>Position</th>
</tr>
</thead>
</table>
#section scripts {
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<script src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js"></script>
<script>
$(document).ready(function () {
$('#myTable').DataTable({
processing: true,
"ajax": {
"type": "GET",
"url": "/DatatableInAnotherWay/GetList",
"dataSrc": function (msg) {
console.log(msg.data);
return msg.data;
}
},
"columns": [
{ "data": "employeeId" },
{ "data": "name" },
{ "data": "age" },
{ "data": "position" },
]
});
});
</script>
}
Note: I am returning as return Json(new { data = empList }); so I would receive response as msg.data. Check the response in your browser console as below:
Importantly, be sure about the column case as you can see I am getting it as lower-case so I bind them as like this"data": "employeeId". As you are saying you are getting in Upper-Case as EmployeeId you should then bind as "data": "EmployeeId"
Final Output:
Special Note:
Remember these words forver, If you want to be a great programmer, you must concentrate on :
Debugging
Code readability
Self reading/teaching attitude
Update:2
If you still want to persist with your code: You could do as following:
$('#myTable').DataTable({
processing: true,
"ajax": {
"type": "GET",
"url": "/Employee/GetList",
"dataSrc": function (msg) {
return msg;
}
},
"columns": [
{ "data": "EmployeeId" },
{ "data": "Name" },
{ "data": "Age" },
{ "data": "Position" },
]
});
Issue on your code:
You were defining the column in worng way: you should do it in following way:
"columns": [
{ "data": "EmployeeId" },
{ "data": "Name" },
{ "data": "Age" },
{ "data": "Position" },
]
Update:2 Output:
Update:
Based on your updated question, its clearly seen that you are ajax calling pattern is incorrect. How your msg.data would be bounded into your "columns": no way. Please try my updated code. Just copy and paste.
I am successfully getting the response back from the database but the
data are not showing inside the table. And i can't figure it out why?
It's because of your row definition in your columns within the datatable.
You would define all of your data members in lower case - like
"columns": [
{ data: "employeeId" },
{ data: "name" },
{ data: "age" },
{ data: "position"},
]
Note: UpperCase EmployeeId, Name etc in jQuery datatable are causing parsing issues. In addition, please follow the $.ajax({}); calling format as per my demo for better code readability.
Complete example:
<table id="myTable" class="table table-striped table-bordered dt-responsive nowrap" width="100%" cellspacing="0">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Age</th>
<th>Position</th>
</tr>
</thead>
</table>
#section scripts {
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<script src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js"></script>
<script>
$(document).ready(function () {
$.ajax({
type: "GET",
url: "/Employee/GetList",
success: function (response) {
$('#myTable').DataTable({
data: response,
columns: [
{ data: 'EmployeeId' },
{ data: 'Name' },
{ data: 'Age' },
{ data: 'Position' }
]
});
},
error: function (response) {
alert(response.responseText);
}
});
});
</script>
}
Output:
How can I call action method from jquery ajax form? I create below code, but parameters in my action method is always null.
Note: I already added all needed scripts, such as quill.js, jquery.unobtrusive-ajax.js
I have this form:
<form data-ajax="true" data-ajax-method="post" method="post">
<input type="text" name="postTitle" class="form-group" />
<div id="postData" name="postData"></div>
<br />
<button type="submit" class="btn btn btn-outline-dark" id="btnCreate">Create post</button>
</form>
and this javascript and jquery scripts:
QUILL:
<script>
var toolbarOptions = [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
[{ 'header': 1 }, { 'header': 2 }], // custom button values
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
[{ 'script': 'sub' }, { 'script': 'super' }], // superscript/subscript
[{ 'indent': '-1' }, { 'indent': '+1' }], // outdent/indent
[{ 'direction': 'rtl' }], // text direction
[{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
['link', 'image', 'video', 'formula'], // add's image support
[{ 'color': [] }, { 'background': [] }], // dropdown with defaults from theme
[{ 'font': [] }],
[{ 'align': [] }],
['clean'] // remove formatting button
];
var quill = new Quill('#postData', {
modules: {
toolbar: toolbarOptions
},
theme: 'snow'
});
</script>
Calling post action method:
$(function () {
$('#btnCreate').click(function () {
var props = [{
"PostTitle": $("postTitle"),
"PostData": quill.root.innerHTML
}]
$.ajax({
url: '#Url.Action("Create", "Post")',
type: "POST",
data: { JSON.stringify(props) },
contentType: "application/json",
dataType: "json",
async: true,
success: successFunc,
error: errorFunc
});
function successFunc(data, status) {
alert(data);
}
function errorFunc(e) {
console.log('Error!', e);
}
//console.log(postData);
});
});
My action method:
[HttpPost]
[ActionName("Create")]
public async Task<IActionResult> CreatePost(string props) // here props is null
{
Post post = new Post { PostBody = props };
db.Posts.Add(post);
await db.SaveChangesAsync();
return View();
}
I think that every input element is obtained from val ();
$("postTitle").val() maybe
I'm trying to bind jQuery DataTable by calling mvc action method using AJAX call and trying to populate the table using JSON data but it gets stuck on loading. Am I missing something?
Also, how can I implement server side Paging, Searching and Sorting in jQuery DataTable.
function initDataTable(ClientId)
{
var assetListVM;
$(function () {
assetListVM = {
dt: null,
init: function () {
var ClientId = $('#ddlClient').val();
dt = $('#records-data-table').dataTable({
"serverSide": true,
"processing": true,
"ajax": {
"type": "POST",
"dataType": "json",
"url": "#Url.Action("GetProcessingData", "Processing")?clientId=" + ClientId,
"success": function (data) {
alert(data);
console.log(data);
},
"error": function(){
alert("Error");
}
},
"columns": [
{ "title": "Co Num",
"data": "CompanyNo",
"searchable": true },
{ "title": "Cycle Date",
"data": "CycleDate",
"searchable": true },
{ "title": "Policy Number",
"data": "PolicyNo",
"searchable": true },
{ "title": "Issue Date",
"data": "IssueDate",
"searchable": true },
{ "title": "Transaction Date",
"data": "TransactionDate"
},
{ "title": "Transaction Amt",
"data": "TransactionAmount"
},
{ "title": "Item Code",
"data": "ItemCode"
},
{ "title": "Account",
"data": "Account"
},
{ "title": "Owner Name",
"data": "OwnerName"
}
],
"lengthMenu": [[10, 25, 50, 100], [10, 25, 50, 100]],
});
}
}
// initialize the datatables
assetListVM.init();
});
}
Below is my action method:
public ActionResult GetProcessingData(int clientId)
{
ClientSummary ClientSUM = new ClientSummary();
List<PolicyDownload> LstPData = new List<PolicyDownload>();
DataTable dtProcessingData = new DataTable();
try
{
using (DLpolicyDownload objDLpolicyDownload = new DLpolicyDownload())
{
dtProcessingData = objDLpolicyDownload.GetProcessingRecordDetails(clientId);
if (dtProcessingData != null)
{
foreach (DataRow dr in dtProcessingData.Rows)
{
PolicyDownload pData = new PolicyDownload();
pData.CompanyNo = Convert.ToInt32(dr["CO_NUM"]);
pData.CycleDate = Convert.ToString(dr["CYCLE_DATE"]);
pData.PolicyNo = Convert.ToString(dr["POLICY_NUMBER"]);
pData.IssueDate = Convert.ToString(dr["ISSUE_DATE"]);
pData.TransactionDate = Convert.ToString(dr["TRANSACTION_DATE"]);
pData.TransactionAmount = Convert.ToDouble(dr["TRANSACTION_AMOUNT"]);
pData.ItemCode = Convert.ToInt32(dr["ITEM_CODE"]);
pData.Account = Convert.ToString(dr["ACCOUNT"]);
pData.OwnerName = Convert.ToString(dr["OWNER_NAME"]);
LstPData.Add(pData);
}
}
}
}
catch (Exception ex)
{
if (logChoice)
{
log.Error(ex.Message, ex);
}
}
var data = from s in LstPData
select s;
return Json(new { data = data }, JsonRequestBehavior.AllowGet);
}
Below is the JSON output of this action method:
{"data":[{"PolicyDownloadID":0,"ImportDate":null,"CycleDate":"10/23/2017","CompanyID":0,"CompanyNo":40,"PolicyNo":"L0000001","PlanCode":null,"InsuranceType":null,"IssueDate":"05/02/2011","TransactionDate":"08/03/2017","TransactionAmount":7545.59,"ItemCode":0,"Account":"SBEN","Mode":null,"ModeAmount":0,"PayerName":null,"OwnerName":"CERNY, RAYMOND C","InsuredName":null,"PayeeName":null,"JointOwner":null,"SBC":0,"SBCAmount":0,"IsActive":false,"CreatedOn":"\/Date(-62135575200000)\/"},{"PolicyDownloadID":0,"ImportDate":null,"CycleDate":"10/23/2017","CompanyID":0,"CompanyNo":6,"PolicyNo":"FGL01234","PlanCode":null,"InsuranceType":null,"IssueDate":"07/23/2010","TransactionDate":"08/02/2017","TransactionAmount":26999.62,"ItemCode":0,"Account":"SBEN","Mode":null,"ModeAmount":0,"PayerName":null,"OwnerName":"BURNHAM, STEVEN L","InsuredName":null,"PayeeName":null,"JointOwner":null,"SBC":0,"SBCAmount":0,"IsActive":false,"CreatedOn":"\/Date(-62135575200000)\/"}]}
Below is the screenshot where it stuck:
It is calling my action method but unable to bind the JSON data.
success function - Must not be overridden as it is used internally in DataTables.
So remove success function and try once, hope it will help you.
DataTables requires json in certain format, look at Ajax tab in DataTables Documentation. Your answer in action don't corresponds to this format.
Try to add wrapper class (real or anonymous) with "data" field, which will be your list of objects.
Few things to take care while implementing server side datatable:
Your datatable in view must match number of columns coming with data.
The column names which you are mentioning in datatable should be same as in database table.
For implementing server side searching, add in a row textboxes below header row for each column. you need to bind each textbox keyup event for relevent column and pass it to server and rebind datatable
I want to send custom object to my controller method with jquery datatables default parameters for paging, sorting, searching and # of records binding.
The issue is :
When I Post object to server using datatable ajax it successfully post my object and also send parameters for length, start and draw BUT stops sending parameters for sorting n searching.
When I do GET request it sends all parameters but not only my custom object and obviously it should not
I want to send custom object with datatable defaults parameters for paging and sorting
WHAT IS THE SOLUTION FOR IT ?
here is code:
$('#example').DataTable({
"processing": true,
"serverSide": true,
"ajax": {
"url": "/Color/Fetch",
"type": 'Post',
// "dataType": "json"
data: { color: $scope.colorSearch }
// dataSrc: 'data'
},
"columns": [
{ "data": "Active" },
{ "data": "Company_Id" },
{ "data": "Id" },
{ "data": "IsActive" },
{ "data": "Name" }
]
});
Controller action:
public JsonResult Fetch(Color color, int draw, int start, int length)
{
string search = Request.QueryString["search[value]"];
int sortColumn = -1;
string sortDirection = "asc";
if (length == -1)
{
length = 90;
}
// note: we only sort one column at a time
if (Request.QueryString["order[0][column]"] != null)
{
sortColumn = int.Parse(Request.QueryString["order[0][column]"]);
}
if (Request.QueryString["order[0][dir]"] != null)
{
sortDirection = Request.QueryString["order[0][dir]"];
}}
Try to use the following approach:
$('#example').DataTable({
"processing": true,
"serverSide": true,
/*
"ajax": {
"url": "/Color/Fetch",
"type": 'Post',
// "dataType": "json"
data: { color: $scope.colorSearch }
// dataSrc: 'data'
},
*/
"ajaxSource": "/Color/Fetch",
//fnServerData method used to inject the parameters into the AJAX call sent to the server-side
"fnServerData": function (sSource, aoData, fnCallback) {
aoData.push({ "name": "color", "value": "Blue" }); // Add some extra data to the sender
$.getJSON(sSource, aoData, function (json) {
/* Do whatever additional processing you want on the callback, then tell DataTables */
fnCallback(json);
});
},
"columns": [
{ "data": "Active" },
{ "data": "Company_Id" },
{ "data": "Id" },
{ "data": "IsActive" },
{ "data": "Name" }
]
});