I am struggling to get serialised JSON data from my controller to display in a Datatable. I previously was able to display data when I was sending it as a 2D array. Now I would like to be able to use my object and match it with the columns (as seen in the second JavaScript). I attempted to follow this solution, but I am unable to see what is wrong after looking at the Datatables docs.
Updated
See below what I currently have. I am trying to have the data come through with named parameters as I wish to have parent rows with a list of child items. These items are visible on selection as seen in this DataTables link. Though I am still unable to get the table working with named parameters via JSON data.
Data:
for (int i = 0; i < 26; i++)
{
list.Add(new MembershipTransactionHistoryModel
{
TransactionDate = "01 May 2014",
StoreName = "Store Name",
CardNumber = "23423566",
TransactionType = "Purchase",
TransactionValue = "$134.25",
PointsEarned = "100",
PointsUsed = "23",
PointsBalance = "40000"
});
}
//return new JavaScriptSerializer().Serialize(list);
return from l in list
select new[] {
l.TransactionDate,
l.StoreName,
l.CardNumber,
l.TransactionType,
l.TransactionValue,
l.PointsEarned,
l.PointsUsed,
l.PointsBalance
};
JavaScript:
var grid = $('#transactionHistoryTable').dataTable({
"bProcessing": true,
"sAjaxSource": 'MembershipTransactionHistoryData',
"fnServerParams": function (aoData) {
aoData.push({ "name": "membershipId", "value": 7 })
},
"aoColumnDefs": [
{
"sTitle": "",
"class": 'details-control',
"orderable": false,
"mData": null,
"aTargets": [0],
"defaultContent": ''
},
{ "sTitle": "Transaction Date", "mData" : "TransactionDate", "aTargets": [1]},
{ "sTitle": "Store Name", "mData": "StoreName", "aTargets": [2] },
{ "sTitle": "Card Number", "mData": "CardNumber", "aTargets": [3] },
{ "sTitle": "Type", "mData": "Type", "aTargets": [4] },
{ "sTitle": "Value", "mData": "Value", "aTargets": [5] },
{ "sTitle": "Points Earned", "mData": "PointsEarned", "aTargets": [6] },
{ "sTitle": "Points Used", "mData": "PointsUsed", "aTargets": [7] },
{ "sTitle": "Points Balance", "mData": "PointsBalance", "aTargets": [8] }
],
"paginate": true,
"scrollY": maxHeight,
"scrollCollapse": false,
"sort": true
});
HTML:
<table id="transactionHistoryTable" class="display" cellspacing="0">
<thead>
<tr>
</tr>
</thead>
<tbody>
</tbody>
</table>
Resulting Error:
DataTables warning: table id=transactionHistoryTable - Requested unknown parameter 'TransactionDate' for row 0. For more information about this error, please see http://datatables.net/tn/4
You have to return it as String Array [] not just a List.
Result should be in Array, it is must: new string[].
Note: After the For loop add below code:
var results = from l in list
select new[] {
l.TransactionDate,
l.StoreName ,
l.CardNumber,
l.TransactionType,
l.TransactionValue,
l.PointsEarned,
l.PointsUsed,
l.PointsBalance
};
return Json(results, JsonRequestBehavior.AllowGet); // Return the Result as a string array.
No need to serialize pro-grammatically. It will be serialized automatically.
Data Table expects your results should be in a array. where as you are passing it as a list of class objects.
Take a look at this DataTables - Server side processing Article.
The way I managed to do this in the end, was to avoid JavaScript entirely and just structure my HTML accordingly via my view's Model.
Eg.
<tbody>
#foreach(var item in Model.GetData())
{
<tr>
<td class="details-control"></td>
<td>#item.TransactionId</td>
<td>#item.TransactionDate</td>
<td>#item.StoreName</td>
<td>#item.CardNumber</td>
<td>#item.TransactionType</td>
<td>#item.TransactionValue</td>
<td>#item.PointsEarned</td>
<td>#item.PointsUsed</td>
<td>#item.PointsBalance</td>
</tr>
}
</tbody>
I then used the documentation from DataTables to construct my sub-item table and performed a post to get that data.
My success method in the ajax post was as below:
success: function (data) {
var html = '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">';
for (var i = 0; i < data.length; i++) {
html += '<tr>' +
'<td>APN:</td>' +
'<td>' + data[i].ProductAPN + '</td>' +
'<td>Desc:</td>' +
'<td>' + data[i].ProductDescription + '</td>' +
'<td>Qty:</td>' +
'<td>' + data[i].Quantity + '</td>' +
'<td>Amount:</td>' +
'<td>' + data[i].Amount + '</td>' +
'<td>Points:</td>' +
'<td>' + data[i].PointsEarned + '</td>' +
'</tr>'
}
html += '</table>';
// Open this row
row.child(html).show();
tr.addClass('shown');
}
Related
I have Issue with this Datatable Jquery i get this Error:DataTables warning: table id=patients - Invalid JSON response. For more information about this error, please see http://datatables.net/tn/1
I do this Function on controller:
[HttpGet]
public JsonResult LoadPatients()
{
// Browser list
var totalPatientsList = _unitOfWork.Patients.GetPatients();
var filteredResult = from b in totalPatientsList
select new[] {b.Jeton, b.Nom, b.TelePhone, b.Adresse, b.Villes.Nom,b.Id.ToString()};
return Json(new
{
data =filteredResult
},
JsonRequestBehavior.AllowGet);
}
and i call on index view :
$(document).ready(function () {
var table = $("#patients").DataTable({
ajax: {
url:"/patients/LoadPatients",
dataSrc: ""
},
columns: [
{
data: "jeton"
},
{
data: "nom"
},
{
data: "telephone",
render: function (data) {
return data.toString().replace(
/(\d\d\d)(\d\d\d)(\d\d\d\d)/g, '$1-$2-$3');
}
},
{
data: "adresse"
},
{
data: "villes.nom"
},
{
data: "id",
render: function (data, type, patient) {
return "<a href='/patients/details/ " + patient.id + "' class='btn btn-default btn-xs'>" + "<i class='fa fa-folder'></i>View</a>" +
//"<button class= 'btn-link js-detail' data-detail-id=" + data + "><i class='fa fa-pencil-square'></i></button>" +
"<button class= 'btn btn-danger btn-xs js-delete' data-patient-id=" + data + "><i class='fa fa-trash-o'></i>Delete</button>";
}
}
]
});
I inspect result on chrome i get that:
{
"data": [
["0002020", "patienta", "0670707070", "Zone franche", "Tan", "1"],
["0002029", "tst", "0524242424", "Ma", "M", "10"]
]
}
How can i resolve this Issue thanks in advance
Your JSON does not have any labels - each row is just a data array, for example:
["0002020", "patienta", "0670707070", "Zone franche", "Tan", "1"]
This means you cannot use data labels like this:
data: "jeton"
because the label jeton does not exist in your JSON data.
So, instead, you can change all of these data:... values to title"... - for example:
title: "jeton"
This means that the first value in the array (which is "0002020") will appear in the first column of your table - and the column heading will be "jeton".
And then the second column in your table will contain "patienta" and will use the column heading of "nom" - and so on.
Here is my example using your data:
I think that is all you need to do to fix the issue.
Extra Notes:
Don't forget to update the ajax URL - it loos like you may have already done that.
You may also need to remove the following dataSrc: "" line from the ajax section, so it is this:
ajax: {
url:"/patients/LoadPatients"
},
but I am not sure. Try it both ways.
Showing "Processing..." in datatable when data is empty in mvc view. I am confusing that why it is showing "Processing...". If there is empty data then it want to show "No data available in table"
Here is my code
[View Side]
<div class="row">
<div class="col-md-12">
<table id="dataGrid" class="display table table-striped table-bordered dt-responsive nowrap" width="100%" cellspacing="0">
<thead>
<tr>
<th>Id</th>
<th>Document Name</th>
<th>Other Document Name</th>
<th>Image</th>
<th>Action</th>
</tr>
</thead>
</table>
</div>
</div>
<script>
$(document).ready(function () {
var data = {
'customerId': #Model.Id,
}
addAntiForgeryToken(data);
// DataTable
$("#dataGrid").DataTable({
"scrollX": true, // scrolling horizontal
"bSort": false,
"bFilter": false,
"processing": true, // for show progress bar
"serverSide": true, // for process server side
"pageLength": 5,
"lengthMenu": [5, 10, 50, 100, 1000, 10000],
"ajax": {
"url": "/Admin/FreeLancer/list",
"type": "POST",
"datatype": "json",
"data": data,
"success": function (data) {
}
},
"columnDefs":
[{
"targets": [0],
"visible": false,
"searchable": false,
"orderable": false,
}
],
"columns": [
{ "data": "Id", "name": "Id", "autoWidth": true },
{ "data": "DocumentName", "name": "DocumentName", "autoWidth": true },
{ "data": "OtherDocumentName", "name": "otherdocumentname", "autoWidth": true },
{ "data": "UploadID", "name": "UploadID", "autoWidth": true },
{
"render": function (data, type, row) {
//return "<a target='_blank' href='/Download/GetDownload?downloadId=" + row.UploadID + "' class='btn btn-info'>Download </a>" +
//"<a href='#' class='btn btn-danger' onclick=DeleteData('" + row.Id + "');>Delete</a>"; }
return "<a href='#' class='btn btn-danger' onclick=DeleteData('" + row.Id + "');>Delete</a>";
}
},
],
});
});
</script>
[Controller Side]
[HttpPost]
public IActionResult List(int customerId)
{
// getting all data
var dataList = _customerRegister.DocumentList(customerId,
start: Convert.ToInt32(Request.Form["start"]),
pageSize: Request.Form["length"].ToString() != null ? Convert.ToInt32(Request.Form["length"].ToString()) : 0,
sortColumnName: Request.Form["columns[" + Request.Form["order[0][column]"] + "][name]"],
sortColumnDirection: Request.Form["order[0][dir]"]);
var data = dataList.Select(x => new
{
Id = x.Id,
DocumentName = x.DocumentName,
OtherDocumentName = x.OtherDocumentName,
UploadID = x.UploadID,
});
//returning json data
Response.StatusCode = 200;
return Json(new { draw = Request.Form["draw"], recordsfiltered = dataList.TotalCount, recordstotal = dataList.TotalCount, data = data });
}
This is the code, but I dont think so that their is any problem in the code
Have you checked the DataTables dom property?
$("#table_selector").DataTable({
dom: 'r<"datatable-header"fl><"datatable-scroll"t><"datatable-footer"ip>',
processing: true,
serverSide: true
});
Options
The built-in table control elements in DataTables are:
l - length changing input control
f - filtering input
t - The table!
i - Table information summary
p - pagination control
r - processing display element
https://datatables.net/reference/option/dom
I can see that there is no code for displaying the message. If you are using JQuery Data table which i have notice you can use:
oLanguage: {
sEmptyTable: "Message",
sZeroRecords: "Message",
},
I am trying a proof of concept in SAPui5 to check the content of a searchfield, bind a result into another field, if i don't have any result i display an error message that has been written in a message field of my odata
so far i succeeded that this way
this.getView().bindElement({
path: "/ExcSet('" + evt.getSource().getValue() + "')",
model: "EXCEPTION",
events: {
dataReceived: function(response) {
if (response.mParameters.data.Message !== '') {
MessageBox.error(response.mParameters.data.Message);
}
}
}
(If someone knows how to do that a better way, because using mParameters is not the best way, it is welcome)
Now, I want to extend my odata call with an expand navigation to display a table of results, by not using another odata call that the one i used already, so here is my code so far :
eanSearch: function(evt) {
var oView = this.getView();
var oTemplate = new ColumnListItem({
cells: [
new Text({
text: "{Volum}"
}),
new Text({
text: "{Voleh}"
})
]
});
this.getView().bindElement({
path: "/ExcSet('" + evt.getSource().getValue() + "')",
model: "EXCEPTION",
parameters: {
expand: "ExcMarmNav"
},
events: {
dataReceived: function(response) {
if (response.mParameters.data.Message !== '') {
MessageBox.error(response.mParameters.data.Message);
}
}
}
});
oView.byId("table").bindItems({
path : '/ExcMarmNav',
template : oTemplate
});
}
The data of the expand is loaded into my response as you can see here
data: {
"ExcSet('5410366897766')": {
"__metadata": {
"id": "http://...:8000/sap/opu/odata/sap/ZEXCEPTION_SRV/ExcSet('5410366897766')",
"uri": "http://...:8000/sap/opu/odata/sap/ZEXCEPTION_SRV/ExcSet('5410366897766')",
"type": "ZEXCEPTION_SRV.Exc"
},
"Matnr": "000000000040000000",
"Ean": "5410366897766",
"Message": "",
"ExcMarmNav": {
"__list": [
"MarmSet(Matnr='40000000',Meinh='EA')"
]
}
},
"MarmSet(Matnr='40000000',Meinh='EA')": {
"__metadata": {
"id": "http://...:8000/sap/opu/odata/sap/ZEXCEPTION_SRV/MarmSet(Matnr='40000000',Meinh='EA')",
"uri": "http://...:8000/sap/opu/odata/sap/ZEXCEPTION_SRV/MarmSet(Matnr='40000000',Meinh='EA')",
"type": "ZEXCEPTION_SRV.Marm"
},
"Matnr": "40000000",
"Meinh": "EA",
"Umrez": "1",
"Umren": "1",
"Eannr": "",
"Ean11": "5410366897766",
"Numtp": "HE",
"Laeng": "20.000",
"Breit": "20.000",
"Hoehe": "10.000",
"Meabm": "CM",
"Volum": "4000.000",
"Voleh": "CCM",
"Brgew": "2.500",
"Gewei": "KG",
"Mesub": "",
"Atinn": "0000000000",
"Mesrt": "00",
"Xfhdw": "",
"Xbeww": "",
"Kzwso": "",
"Msehi": "",
"BflmeMarm": "",
"GtinVariant": "",
"NestFtr": "0",
"MaxStack": 0,
"Capause": "0.000",
"Ty2tq": ""
}
}
But i don't know how to use resultset to bind it into a table, my code above is not working, if someone has an idea of the params to use for my binditems, or if there is another way to do it?
Best regards
Denis
I managed to do the binding of my table using an intermediate JSON Model based on the response of the Odata Model
eanSearch: function(evt) {
var oView = this.getView();
this.getView().bindElement({
path: "/ExcSet('" + evt.getSource().getValue() + "')",
model: "EXCEPTION",
parameters: {
expand: "ExcMarmNav"
},
events: {
dataReceived: function(response) {
if (response.mParameters.data.Message !== '') {
MessageBox.error(response.mParameters.data.Message);
} else {
var model = new JSONModel({
"items": response.mParameters.data.ExcMarmNav
});
oView.setModel(model, "itemModel");
}
}
}
});
And this is the XML view:
<Table id="table" items="{itemModel>/items}">
<columns>
<Column><Label/></Column>
<Column><Label/></Column>
</columns>
<ColumnListItem>
<cells>
<Text text="{itemModel>Volum}"/>
<Text text="{itemModel>Voleh}"/>
</cells>
</ColumnListItem>
</Table>
works fine but I would like to avoid using the intermediate JSON Model and bind directly the array of the response in the table
Ok I managed to find what I needed :)
so the controller:
eanSearch: function(evt) {
var oView = this.getView();
this.getView().bindElement({
path: "/ExcSet('" + evt.getSource().getValue() + "')",
model: "EXCEPTION",
parameters: {
expand: "ExcMarmNav"
},
events: {
dataReceived: function(response) {
if (response.mParameters.data.Message !== '') {
MessageBox.error(response.mParameters.data.Message);
}
}
}
});
}
and the view:
<Table noDataText="No Data" items="{EXCEPTION>ExcMarmNav}">
<columns>
<Column><Label/></Column>
<Column><Label/></Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Text text="{EXCEPTION>Volum}"/>
<Text text="{EXCEPTION>Voleh}"/>
</cells>
</ColumnListItem>
</items>
</Table>
var headers = [{ "mDataProp": "Agents" },{ "mDataProp": "Buyer" },{ "mDataProp": "Date" }];
$(document).ready(function () {
$('#data-table').dataTable({
"bFilter": false,
"bLengthChange": false,
"iDisplayLength": 25,
"bJQueryUI": true,
"bServerSide": true,
"bProcessing": true,
"sPaginationType": "full_numbers",
"aoColumns": headers,
"sAjaxSource": '/report/TestPaging',
});
});
If I remove the aoColumns from my code the datatable is generated normally, but when I add aoColumns I get :
DataTables warning (table id = 'data-table'): Requested unknown parameter 'Agents' from the data source for row 0
HTML:
<table id="data-table">
<thead>
<tr>
<th>tmp</th>
<th>tmp</th>
<th>tmp</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
How can I configure header names? I need them for my sorting.
Do they have to be same as in "th" tags?
Json response from my controller is ok because it renders fine when I remove aoColumns
I have string[][](var data) with 3 strings in each line and return it as
Json(new{
sEcho = param.sEcho,
iTotalRecords = visitRepository.Query.Count(),
iTotalDisplayRecords = visitRepository.Query.Count(),
aaData = data
}, JsonRequestBehavior.AllowGet);
The error you are experiencing is caused by a mismatch between the contents of the JSON and your aoColumns definition. The names you are targeting in aoColumns must be exactly the same as those in the JSON, and the length of each object in the JSON must be equal to the number of columns in the original HTML table. See the docs for clarification. In your case, the JSON should look like this :
[{
"Agents": "tM4Ga0zX",
"Buyer": "ZKwMEiIa",
"Date": "K3lS2yn9"
},
...]
...And your JSON doesnt follow that scheme. If you are not using aoColumns, then the data is inserted by index, not by name - and that is why it is working for you without it.
You configure header names (titles) by the sTitle property :
aoColumns: [
{ mDataProp: "Agents", sTitle : "Agents" },
{ mDataProp: "Buyer", sTitle : "Buyer" },
{ mDataProp: "Date", sTitle : "Date" }
]
see this demonstration based on your question -> http://jsfiddle.net/kLR7G/
i am having issues with paging on server side with datatables jquery plugin. The paging control at the bottom of the grid shows
Showing 1 to 10 of 10 entries (filtered from 7,253 total entries)
but am not filtering any records. If I click the next or previous links no ajax requests are being sent back to the server. I would expect to see
Showing 1 to 10 of 7253 entries.
Controller Code
public ActionResult GetDataTable(DataTableParamModel param)
{
var allhotelscount = db.Businesses.OfType<Hotel>().Count();
var filteredhotels = db.Businesses.OfType<Hotel>().OrderBy(h => h.Name);
IEnumerable<DataTableHotel> displayedhotels = from c in filteredhotels
.Skip(param.iDisplayStart).Take(param.iDisplayLength)
select new DataTableHotel
{
Id = c.Id,
Name = c.Name,
CityState = c.PhysicalCity + ", " + c.PhysicalState,
PhoneNumber = c.PhoneNumber,
PrimaryContact = c.PrimaryContact.FirstName + " " + c.PrimaryContact.LastName,
PrimaryContactPhone = c.PrimaryContact.OfficePhone,
PrimaryContactEmail = c.PrimaryContact.EmailAddress,
};
return Json(new
{
sEcho = param.sEcho,
iTotalRecords = allhotelscount,
iTotalDisplayRecords = displayedhotels.Count(),
aaData = displayedhotels
},
JsonRequestBehavior.AllowGet);
}
View Code:
<table id="myDataTable" class="display">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>City, State</th>
<th>Phone</th>
<th>Contact</th>
<th>Phone</th>
<th>Email</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script type="text/javascript">
$(document).ready(function () {
$('#myDataTable').dataTable({
"bServerSide": true,
"sAjaxSource": "/Hotel/GetDataTable",
"bProcessing": true,
"aoColumns": [
{ "mData": "Id" },
{ "mData": "Name" },
{ "mData": "CityState" },
{ "mData": "PhoneNumber" },
{ "mData": "PrimaryContact" },
{ "mData": "PrimaryContactPhone" },
{ "mData": "PrimaryContactEmail" },
]
});
});
You passed a wrong value to iTotalDisplayRecords, see below code:
return Json(new
{
sEcho = param.sEcho,
iTotalRecords = allhotelscount,
iTotalDisplayRecords = allhotelscount,
aaData = displayedhotels
},
JsonRequestBehavior.AllowGet);