I have used jquery datatable Server-side processing in my application (asp web form ), after the data returned, paging, searching and sorting do not work. I've read several cases here on the forum of similar or equal problems, but I still haven't been able to solve mine. Could you look at my code, please?
datatable
<script type="text/javascript">
$(document).ready(function () {
$("#stockDatatable").DataTable({
"processing": true, //show processing message
"serverSide": true, //is server side
"filter": true, //allow filter
"ajax": {
"url": "WebForm2.aspx/GetData", //endpoint to get data
"contentType": "application/json",
"type": "GET",
"dataType": "JSON",
"data": function (d) {
return d;
},
"dataSrc": function (json) {
json.draw = json.d.draw;
json.recordsTotal = json.d.recordsTotal;
json.recordsFiltered = json.d.recordsFiltered;
json.data = json.d.data;
var return_data = json.d.data;
return return_data;
}
},
"columns": [ // columns to populate
{ "data": "Id" },
{ "data": "Code"},
{ "data": "Type" },
{ "data": "Text_Description" },
{ "data": "Date_Time" },
{ "data": "Date_Created"},
{ "data": "Added_by" },
],
});
});
</script>
Code Behind (Webform2.cs)
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
public static object GetData()
{
DataTables result = new DataTables();
using (var db = new MunchData())
{
string search = HttpContext.Current.Request.Params["search[value]"];
string draw = HttpContext.Current.Request.Params["draw"];
string order = HttpContext.Current.Request.Params["order[0][column]"];
string sortColumnDirection = HttpContext.Current.Request.Params["order[0][dir]"];
int startRec = Convert.ToInt32(HttpContext.Current.Request.Params["start"]);
int pageSize = Convert.ToInt32(HttpContext.Current.Request.Params["length"]);
string start = HttpContext.Current.Request.Params["start"];
int skip = start != null ? Convert.ToInt32(start) : 0;
var data = db.Machineinfoes.OrderByDescending(p => p.Id).ToList();
int totalRecords = data.Count;
int recFilter = data.Count;
result.draw = Convert.ToInt32(draw);
result.recordsTotal = totalRecords;
result.recordsFiltered = recFilter;
result.data = data.Skip(skip).Take(pageSize).ToList();
}
return result;
}
Related
I have read this post
I'm moving from MVC .Net Core to Blazor. I'm using Datatable with MVC but I want to reuse it. But I'm using ajax function from datatable. Here the JS code:
function AddDataTable(elementName, controller, columns, columnDefs, actionMethod = "/Search") {
var table = $(elementName).DataTable(
{
"lengthMenu": [[10, 25, 50, 100], [10, 25, 50, 100]],
"searching": true,
"processing": true,
"serverSide": true,
"filter": true,
"orderMulti": true,
"pageLength": 10,
"pagingType": "simple_numbers",
"ajax": {
"url": controller + actionMethod,
"type": "POST",
"datatype": "json",
"error": function (xhr, error, thrown) {
if (xhr.status === 405) {
window.location.href = urlBase + "StatusCode/" + xhr.status;
}
return EmptyTable(elementName, controller, columns, columnDefs);
},
},
"columns": columns,
"columnDefs": columnDefs
}
);
return table;
}
API (C# .Net Core)
[HttpPost]
[Route("Datatable")]
public IActionResult Search(string start, string length, string sortColumn, string sortColumnDir, string searchValue, string draw = null)
{
try
{
int pageSize = length != null ? Convert.ToInt32(length) : 0;
int skip = start != null ? Convert.ToInt32(start) : 0;
int recordsTotal = 0;
var list= _context.Entity;
if (!(string.IsNullOrEmpty(sortColumn) && !string.IsNullOrEmpty(sortColumnDir)))
{
list= list.OrderBy(sortColumn + " " + sortColumnDir);
}
List<Entity> data;
if (!string.IsNullOrEmpty(searchValue))
{
list= list.Where(m => m.property.Contains(searchValue));
recordsTotal = list.Count();
}
else
{
recordsTotal = list.Count();
}
data = list.Skip(skip).Take(pageSize).ToList();
return Ok(new { draw = draw, recordsFiltered = recordsTotal, recordsTotal = recordsTotal, data = data });
}
catch (Exception ex)
{
return Conflict();
}
}
In my Blazor APP I moved script and implemented the code in this post it works but it first call all my data and then only filter, sort and search but in client side. I want implement a way to call it from Blazor
Actually on my Blazor app just call Datatable in this way:
protected async override Task OnAfterRenderAsync(bool firstRender)
{
await JSRuntime.InvokeAsync<string>("AddDataTable", new object[] { "#" + id + " table", Searchable });
await base.OnAfterRenderAsync(firstRender);
}
My script in Blazor App
function AddDataTable(table, searching) {
$(table).DataTable({
"searching": searching
});
}
There is a way to reuse it?
The problems is Datatables JS stays in state "processing" and the Chrome debug throws:
Uncaught TypeError: Cannot read property 'length' of undefined
The code in question that "feeds" datatables js is (data is some linq query):
var jsonData = Json(data);
return jsonData;
The response is (textual response):
[{
"TotalCredito": 1649112940.000000,
"TotalClientes": 1040,
"Balance7": 188974066.000000,
"Balance37": 25152742.000000,
"Balance67": 53268069.000000,
"Mes": 1
}, {
"TotalCredito": 1910576150.000000,
"TotalClientes": 941,
"Balance7": 332301396.000000,
"Balance37": 84407873.000000,
"Balance67": -7053061.000000,
"Mes": 2
}, {
"TotalCredito": 1852843443.000000,
"TotalClientes": 809,
"Balance7": 300589569.000000,
"Balance37": 87170595.000000,
"Balance67": 41900708.000000,
"Mes": 3
}, {
"TotalCredito": 1736522626.000000,
"TotalClientes": 747,
"Balance7": 235758479.000000,
"Balance37": 107699635.000000,
"Balance67": 60831390.000000,
"Mes": 4
}, {
"TotalCredito": 1611546395.000000,
"TotalClientes": 702,
"Balance7": 201209547.000000,
"Balance37": 59028449.000000,
"Balance67": 64171607.000000,
"Mes": 5
}, {
"TotalCredito": 1306131513.000000,
"TotalClientes": 697,
"Balance7": 552835099.000000,
"Balance37": 67349028.000000,
"Balance67": 50490441.000000,
"Mes": 6
}]
And the script function in the view is:
<script>
$(document).ready(function () {
var datatable = $('#informe').dataTable({
"language": { "url": "http://cdn.datatables.net/plug-ins/28e7751dbec/i18n/Spanish.json" },
"bFilter": false,
"processing": true,
"serverSide": true,
"ajax": {
"url": "somesupercoolurl",
"type": "POST",
"dataType": "json"
},
"columns": [
{ "data": "Balance7" },
{ "data": "Balance37" },
{ "data": "Balance67" },
{ "data": "Mes" },
{ "data": "TotalClientes" },
{ "data": "TotalCredito" }
],
});
});
Finally, the table is:
<table id="informe">
<thead>
<tr>
<th>Balance7</th>
<th>Balance37</th>
<th>Balance67</th>
<th>Mes</th>
<th>TotalClientes</th>
<th>TotalCredito</th>
</tr>
</thead>
</table>
I find it strange that while the information is properly formatted, is not able to process.
Finally, i resolve this
after seeing many examples, I noticed it's necessary include this 3 variables to json before parse the json object to datatables js; In the controller:
var totalDatos = data.Count();
var jsonData = Json(new {
iTotalDisplayRecords = totalDatos,
iTotalRecords = totalDatos,
aaData = data
});
return jsonData;
Whit this 'function', the json object is like this
{"iTotalDisplayRecords":6,"iTotalRecords":6,"aaData":[{"TotalCredito":1649112940.000000,"TotalClientes":1040,"Balance7":188974066.000000,"Balance37":25152742.000000,"Balance67":53268069.000000,"Mes":1},{"TotalCredito":1910576150.000000,"TotalClientes":941,"Balance7":332301396.000000,"Balance37":84407873.000000,"Balance67":-7053061.000000,"Mes":2},{"TotalCredito":1852843443.000000,"TotalClientes":809,"Balance7":300589569.000000,"Balance37":87170595.000000,"Balance67":41900708.000000,"Mes":3},{"TotalCredito":1736522626.000000,"TotalClientes":747,"Balance7":235758479.000000,"Balance37":107699635.000000,"Balance67":60831390.000000,"Mes":4},{"TotalCredito":1611546395.000000,"TotalClientes":702,"Balance7":201209547.000000,"Balance37":59028449.000000,"Balance67":64171607.000000,"Mes":5},{"TotalCredito":1306131513.000000,"TotalClientes":697,"Balance7":552835099.000000,"Balance37":67349028.000000,"Balance67":50490441.000000,"Mes":6}]}
The table, in the view:
<table id="informe">
<thead>
<tr>
<th>Mes</th>
<th>TotalCredito</th>
<th>TotalClientes</th>
<th>Balance7</th>
<th>Balance37</th>
<th>Balance67</th>
</tr>
</thead>
</table>
The Script is:
<script>
$(document).ready(function () {
var arrayDatos = {
'canal': $(" #ListaCanales ").val(),
'anio': $(" #ListaAnios ").val(),
'vendedorsigla': $(" #ListaVendedores ").val()
};
var datatable = $('#informe').dataTable({
"language": { "url": "http://cdn.datatables.net/plug-ins/28e7751dbec/i18n/Spanish.json" },
"bFilter": false,
"processing": true,
"serverSide": true,
"ajax": {
"url": "mensualajax",
"type": "POST",
"dataType": "json",
"data": arrayDatos
},
"columns": [
{ "data": "Mes", "bSortable": false },
{ "data": "TotalCredito" },
{ "data": "TotalClientes" },
{ "data": "Balance7" },
{ "data": "Balance37" },
{ "data": "Balance67" }
],
});
$(" #FiltrarResultados ").click(function () {
var arrayDatos = {
'canal': $(" #ListaCanales ").val(),
'anio': $(" #ListaAnios ").val(),
'vendedorsigla': $(" #ListaVendedores ").val()
};
datatable.fnClearTable();
$('#informe').dataTable({
"bDestroy": true,
"language": { "url": "http://cdn.datatables.net/plug-ins/28e7751dbec/i18n/Spanish.json" },
"bFilter": false,
"processing": true,
"serverSide": true,
"ajax": {
"url": "mensualajax",
"type": "POST",
"dataType": "json",
"data": arrayDatos
},
"columns": [
{ "data": "Mes", "bSortable": false },
{ "data": "TotalCredito" },
{ "data": "TotalClientes" },
{ "data": "Balance7" },
{ "data": "Balance37" },
{ "data": "Balance67" }
],
});
});
});
is important remark, i use the 'click' function to reload whit ajax the datatables, the 'click' function is nearly equal to the another, but i aggregate "bDestroy": true,in the datatable constructor to reload the datatables (It is not very elegant, but work).
Finally, my new superduper controller to render, capture and updating data with DatatablesJs
//repository with the query
var repositorio = new Repositorios.InformeMensualController();
//capture ajax
string canal = String.Join("", Request.Form.GetValues("canal"));
string auxAnio = String.Join("", Request.Form.GetValues("anio"));
int anio = Convert.ToInt32(auxAnio);
string auxVendedorCodigo = String.Join("", Request.Form.GetValues("vendedorsigla"));
int vendedorCodigo = Convert.ToInt32(auxVendedorCodigo);
//set up data
var data = repositorio.CargaDatos(canal, anio, vendedorCodigo);
//Transformación a JSON y Datatables JS.
var totalDatos = data.Count();
var jsonData = Json(new {
iTotalDisplayRecords = totalDatos,
iTotalRecords = totalDatos,
aaData = data});
return jsonData;
I hope this is useful to someone
regards! :)
I would like add columns dynamically in DataTables.
I retrieve an array with the values for the title of my DataTables.
For the first column, I want nothing and then I want to put my array with the values.
I use Ajax to retrieve the values for titles of DataTables in allyearstat11 .
Here is my javascript code :
function getStatistic11() {
var response;
var allstat11 = [];
var allyearstat11 = [];
var nbY = 20;
$.ajax({
type: 'GET',
url: 'http://localhost:52251/Service1.asmx/Statistic_11',
data: "nbYear='" + nbY + "'",
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (msg) {
response = msg.d;
for (var i = 0; i < response.Items.length; i++) {
allstat11[i] = new Array(nbY);
var j = 0;
allstat11[i][j] = response.Items[i].Interventie;
var t = 1;
while (j <= nbY) {
allstat11[i][t] = response.Items[i].Sum[j];
t++;
j++;
}
}
for (var k = 0; k <= nbY; k++) {
allyearstat11[k] = response.Items[0].YearStart + k;
}
fillDataTable11(allstat11, allyearstat11);
},
error: function (e) {
alert("error loading statistic 11");
}
});
}
Here is my javascript code that fills the DataTables, it works well but manually
function fillDataTable11(data, allyearstat11) {
if ($("#table_statistic_11").css("visibility") == "hidden")
$("#table_statistic_11").css("visibility", "visible");
$('#table_statistic_11').dataTable({
'aaData': data,
'aoColumns': [
{ "sTitle": "", "sCellType": "th", "fnCreatedCell": function (cell) { cell.scope = 'row'; } },
{ "sTitle": allyearstat11[0] },
{ "sTitle": allyearstat11[1] },
{ "sTitle": allyearstat11[2] },
{ "sTitle": allyearstat11[3] },
{ "sTitle": allyearstat11[4] },
{ "sTitle": allyearstat11[5] },
{ "sTitle": allyearstat11[6] },
{ "sTitle": allyearstat11[7] },
{ "sTitle": allyearstat11[8] },
{ "sTitle": allyearstat11[9] },
{ "sTitle": allyearstat11[10] },
{ "sTitle": allyearstat11[11] },
{ "sTitle": allyearstat11[12] },
{ "sTitle": allyearstat11[13] },
{ "sTitle": allyearstat11[14] },
{ "sTitle": allyearstat11[15] },
{ "sTitle": allyearstat11[16] },
{ "sTitle": allyearstat11[17] },
{ "sTitle": allyearstat11[18] },
{ "sTitle": allyearstat11[19] },
{ "sTitle": allyearstat11[20] }
],
"iDisplayLength": 12,
"bJQueryUI": true,
"bDestroy": true,
"bPaginate": false,
"bLengthChange": false,
"bFilter": false,
"bSort": false,
"bInfo": false,
"bAutoWidth": false
});
}
Can I use for loop in "aoColumns"?
How do I do ?
I solved the problem :
var tabTitleColumn = [];
for (var i = 0; i < allyearstat11.length; i++) {
tabTitleColumn.push({
"sTitle": allyearstat11[i],
});
};
And after :
'aoColumns': tabTitleColumn
Hi I have a mDataProp DateTime formatting issue. Basically I want to display the date in one column and the time in another.
But as I understand it the mDataProp is directly related to your model, which does not have a time property just a adate......
Controller
var result = from a in data
select new
{
appointmentDate = a.AppointmentDate.ToShortDateString(),//.ToString("g"),
appointmentTime = a.AppointmentDate.ToLocalTime().ToString("t"),
appointmentName = a.AppointmentType.AppName,
appointmentID = a.AppointmentID
};
//Return Json data for Datatable
return Json(new
{
sEcho = param.sEcho,
iTotalRecords = total,
iTotalDisplayRecords = total,
aaData = result
});
View
<script>
$(document).ready(function () {
var urlRequest = $('#apptTable').data("request-url");
var detailRequest = $('#apptTable').data("detail-url");
$('#apptTable').dataTable({
"bSort": false,
"bServerSide": true,
"sAjaxSource": urlRequest,
"sServerMethod": "POST",
"bProcessing": true,
"bFilter": false,
"aoColumns": [
{ "mDataProp": "appointmentDate" },
{ "mDataProp": "appointmentDate" },
{ "mDataProp": "appointmentName" },
{
"mDataProp": "appointmentID",
"fnRender": function (oObj) {
return 'Details';
}
}
]
});
});
</script>
I cannot create a second variable called appointmentDate in the controller, so I'll have to format in the view.
Any ideas?
I have two datatables, one which lists foldes, and another which list's files within their parent folder. Here is how my script looks for the folder table:
var oTable = $('#folderTable').dataTable({
"bServerSide": true,
"sAjaxSource": "AJAXViewFolders",
"bProcessing": true,
"bFilter": false,
"aoColumns": [
{ "sName": "folder_id",
"bSearchable": false,
"bSortable": false,
"fnRender": function (oObj) {
return 'View';
}
},
{ "sName": "folder_name" },
{ "sName": "create_date" }
]
});
});
Now, when the user clicks the link I need to be able to pass that parentid to the file datatable. I have had no luck thus far. Here is how the JSON result looks in my controller, for the files datatable:
public JsonResult AJAXViewFiles(DataTableParamModel dtParams, int parentid)
{
var repo = new TrusteeDocumentRepository();
var allDocuments = repo.FindAllFiles().Where(c=>c.folder_id == parentid);
IEnumerable<Files> filteredFiles;
filteredFiles = allDocuments;
var displayedFiles = filteredFiles.Skip(dtParams.iDisplayStart).Take(dtParams.iDisplayLength);
var result = from c in displayedFiles select new[] { Convert.ToString(c.folder_id),c.file_name, c.upload_date.ToString() };
return Json(new
{
sEcho = dtParams.sEcho,
iTotalRecords = allDocuments.Count(),
iTotalDisplayRecords = filteredFiles.Count(),
aaData = result
},
JsonRequestBehavior.AllowGet);
}
How would I go about getting the link in the folder table to pass the parentid to the jsonresult for the file's datatable successfully?
I assume the dataTables are on the same page so I'd switch it to a button...
"fnRender": function (oObj) {
return '<button type="button" class="folder-view" data-id="' + oObj.aData[0] + '">View</button>';
}
Add a live click handler so you can set the current parentid and refresh the files dataTable. Handler might look like this...
$('.folder-view').on('click', function() {
var $filesTable = $('#filesTable');
$filesTable.attr('data-parentid', $(this).attr('data-id'));
//refresh the files table
$filesTable.dataTable().fnDraw(false);
});
Finally, the files dataTable will need to override the fnServerData function to merge the extra parentid data...
"fnServerData": function (sSource, aoData, fnCallback) {
var extraData = [ { parentid: $('#filesTable').attr('data-parentid') } ];
$.ajax({
"dataType": "json",
"type": "POST",
"url": sSource,
"data": $.merge(extraData, aoData),
"success": fnCallback
});
}