edit jquery dt response before render - datatables

I have serverside pagination datatable with defination below, it works fine but the thing is;one of the field contains too long so I need to set a details button instead of it, when its clicked pop up showns up and view the data of descripotion.
I tried add success:function(aaData){..} to ajax but it brokes the datatable any suggestion? and I dont want to edit tho model in controller I have data in browser so I want to handle this here..
$(document).ready(function () {
var table = $('#dtBooks').DataTable({
"processing": true,
"serverSide": true,
"filter": false,
"orderMulti": false,
"ajax": {
"url": "#Url.Action("GetBooks", "Home")",
"type": "POST",
"datatype": "json"
},
"columns": [
{ "data": "Title", "name": "Title", "autoWidth": true },
{ "data": "Publisher", "name": "Publisher", "autoWidth": true },
{ "data": "Description", "name": "Description", "autoWidth": true },
{ "data": "Authors", "name": "Authors", "autoWidth": true },
]
});
});
here is the model defination contorller response list of this model to datatable.
public class Book
{
public string Title { get; set; }
public string Publisher { get; set; }
public string Description { get; set; }
public string[] Authors { get; set; }
}

You can use ajax.dataSrc option to manipulate the data returned from the server.
For example:
$('#example').DataTable( {
"ajax": {
"url": "data.json",
"dataSrc": function ( json ) {
for ( var i=0, ien=json.data.length ; i<ien ; i++ ) {
json.data[i][0] = '<a href="/message/'+json.data[i][0]+'>View message</a>';
}
return json.data;
}
}
});

Related

.NET 5 Web Application Throwing Incorrect Content-Type Error when retrieving data for my datatable

I am trying to use datatables.js in my .NET 5 Web App. When I go to run the app in Visual Studio (IIS) I get a 500 error Incorrect Content-Type. I followed the video found here: https://www.youtube.com/watch?v=NITZdsE5Keg There were no comments on the video. I have tried troubleshooting but I have not been able to figure out what is wrong with my controller and why it is throwing this error:
System.InvalidOperationException: Incorrect Content-Type:
at Microsoft.AspNetCore.Http.Features.FormFeature.ReadForm()
at Microsoft.AspNetCore.Http.DefaultHttpRequest.get_Form()
at DatatableSample.Controllers.StudentController.GetStudents() in C:\path\DatatableSample\DatatableSample\Controllers\StudentController.cs:line 30
Here is my Controller:
{
[Route("api/[controller]")]
[ApiController]
public class StudentController : ControllerBase
{
private readonly ApplicationDbContext context;
public StudentController(ApplicationDbContext context)
{
this.context = context;
}
[HttpPost]
public IActionResult GetStudents()
{
try
{
var draw = Request.Form["draw"].FirstOrDefault();
var start = Request.Form["start"].FirstOrDefault();
var length = Request.Form["length"].FirstOrDefault();
var sortColumn = Request.Form["columns[" + Request.Form["order[0][column]"].FirstOrDefault() + "][name]"].FirstOrDefault();
var sortColumnDirection = Request.Form["order[0][dir]"].FirstOrDefault();
var searchValue = Request.Form["search[value]"].FirstOrDefault();
int pageSize = length != null ? Convert.ToInt32(length) : 0;
int skip = start != null ? Convert.ToInt32(start) : 0;
int recordsTotal = 0;
var customerData = (from tempstudent in context.Students select tempstudent);
if(!string.IsNullOrEmpty(sortColumn) && string.IsNullOrEmpty(sortColumnDirection))
{
customerData = customerData.OrderBy(sortColumn + "" + sortColumnDirection);
}
if(!string.IsNullOrEmpty(searchValue))
{
customerData = customerData.Where(m => m.FirstName.Contains(searchValue) || m.LastName.Contains(searchValue) || m.Email.Contains(searchValue));
}
recordsTotal = customerData.Count();
var data = customerData.Skip(skip).Take(pageSize).ToList();
var jsonData = new { draw = draw, recordsFiltered = recordsTotal, recordsTotal = recordsTotal, data = data};
return Ok(jsonData);
}
catch (Exception)
{
throw;
}
}
}
}
Here is my JS file for the datatable:
$(document).ready(function () {
$("#studentDatatable").DataTable({
"processing": true,
"severSide": true,
"filter": true,
"ajax": {
"url": "/api/student",
"type": "POST",
"datatype": "json"
},
"columnDefs": [{
"targets": [0],
"visable": false,
"searchable": false
}],
"columns": [
{ "data": "Id", "name": "Id", "autoWidth": true },
{ "data": "FirstName", "name": "First Name", "autoWidth": true },
{ "data": "LastName", "name": "Last Name", "autoWidth": true },
{ "data": "Email", "name": "Email", "autoWidth": true }
]
}); });
Here is what I have in StartUp.cs to add the database:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), b => b.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)));
services.AddControllers();
services.AddRazorPages();
}
Any help or suggestions is appreciated. I am really at a loss as to what is happening.

return Page() in ASP.NET Core Razor Pages doesn't render the page after calling by RedirectToPage

I'm new to ASP.NET Core Razor Pages.
In the index page I get the customers data and show them in a jQuery data table by ajax from the CustomerController. In the last column there are delete buttons. By these buttons I call delete method in the CustomerController.
JS Ajax file
$(document).ready(function() {
$("#customerDataTable").dataTable({
"processing": true,
"serverSide": true,
"filter": true,
"ajax": {
"url": "/api/customer",
"type": "post",
"datatype": "json"
},
"columnDefs":[
{
"targets": [0],
"visible": false,
"searchable": false
}],
"columns":[
{ "data": "id", "name": "Id", "autoWidth": true },
{ "data": "firstName", "name": "First Name", "autoWidth": true },
{ "data": "lastName", "name": "Last Name", "autoWidth": true },
{ "data": "contact", "name": "Contact", "autoWidth": true },
{ "data": "email", "name": "Email", "autoWidth": true },
{ "data": "dateOfBirth", "name": "Date Of Birth", "autoWidth": true },
{
"render": function(data,type, row) {
return "<a href='#' class='btn btn-danger' onclick=deleteCustomer('" + row.id + "');
>Delete</a>"; }
}]
});
});
function deleteCustomer(id) {
$.ajax({
url: "/api/customer",
type: "GET",
data: id
});
}
In the CustomerContoller I want to redirect to DeleteCustomer razor page with a parameter.
[HttpGet]
public IActionResult DeleteCustomer()
{
var id = Request.Query.Keys.ToList()[0];
return RedirectToPage("/DeleteCustomer", new{id});
}
In the DeleteCustomer Page there is a simple get method.
[BindProperty]
public int CustomerId { get; set; }
public IActionResult OnGet(string id)
{
CustomerId = int.Parse(id);
return Page();
}
When I debug the app line by line CustomerControll redirect to DeleteCustomer page properly, and the OnGet method in the page return the Page() method, but browser doesn't render the HTML part of the page without any errors. Just Index page still showed with the table of data.
If I call DeleteCustomer page in address bar DeleteCustomer page will rendered.
Why return Page() doesn't render and show the page after calling by RedirectToPage in the browser?
Why return Page() doesn't render and show the page after calling by RedirectToPage in the browser?
You make Ajax request from your client side, which does not automatically reload/refresh page. To display returned page content, you can try to dynamically write it in success callback function, like below.
$.ajax({
url: "/api/customer",
type: "GET",
data: id,
success: function (res) {
//console.log(res);
document.write(res);
}
});
Besides, you can also try to modify the approach to make your API action DeleteCustomer return an id, then do redirection on client side, like below.
[HttpGet]
public IActionResult DeleteCustomer()
{
//your code logic here
//var id = Request.Query["id"];
//return RedirectToPage("/DeleteCustomer", new { id });
return Ok(new { id });
}
On client side
success: function (res) {
console.log(res.id[0]);
window.location.assign("/DeleteCustomer?id=" + res.id[0]);
//document.write(res);
}

Sort icon not changing in Datatable server side processing

When I use server side processing in datatable the sorting works but the sort icon does not change and stays in same direction. Below is the code snippet of my datatable configuration.
$('#dtSearchResult').DataTable({
"filter": false,
"pagingType": "simple_numbers",
"orderClasses": false,
"order": [[0, "asc"]],
"info": true,
"scrollY": "450px",
"scrollCollapse": true,
"bLengthChange": false,
"searching": true,
"bStateSave": false,
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": VMCreateExtraction.AppSecurity.websiteNode() + "/api/Collection/SearchCustIndividual",
"fnServerData": function (sSource, aoData, fnCallback) {
aoData.push({ "name": "ccUid", "value": ccUid });
//Below i am getting the echo that i will be sending to Server side
var echo = null;
for (var i = 0; i < aoData.length; i++) {
switch (aoData[i].name) {
case 'sEcho':
echo = aoData[i].value;
break;
default:
break;
}
}
$.ajax({
"dataType": 'json',
"contentType": "application/json; charset=utf-8",
"type": "GET",
"url": sSource,
"data": aoData,
success: function (msg, a, b) {
$.unblockUI();
var mappedCusNames = $.map(msg.Table, function (Item) {
return new searchGridListObj(Item);
});
var data = {
"draw": echo,
"recordsTotal": msg.Table2[0].TOTAL_NUMBER_OF_RECORDS,
"recordsFiltered": msg.Table1[0].FILTERED_RECORDS,
"data": mappedCusNames
};
fnCallback(data);
$("#dtSearchResult").show();
ko.cleanNode($('#dtSearchResult')[0]);
ko.applyBindings(VMCreateExtraction, $('#dtSearchResult')[0]);
}
})
},
"aoColumns": [{
"mDataProp": "C_UID"
}, {
"mDataProp": "C_LAST_NAME"
}, {
"mDataProp": "C_FIRST_NAME"
}, {
"mDataProp": "C_USER_ID"
}, {
"mDataProp": "C_EMAIL"
}, {
"mDataProp": "C_COMPANY"
}],
"aoColumnDefs": [{ "defaultContent": "", "targets": "_all" },
//I create a link in 1 st column
]
});
There is some configuration that I am missing here. I read on datatable forums and the only issue highlighted by people was that draw should be same as what we send on server side.
For anyone looking for an answer to this. Sad but i had to write my own function as below:
function sortIconHandler(thArray, sortCol, sortDir) {
for (i = 0; i < thArray.length; i++) {
if (thArray[i].classList.contains('sorting_asc')) {
thArray[i].classList.remove('sorting_asc');
thArray[i].classList.add("sorting");
}
else if (thArray[i].classList.contains('sorting_desc')) {
thArray[i].classList.remove('sorting_desc');
thArray[i].classList.add("sorting");
}
if (i == sortCol) {
if (sortDir == 'asc') {
thArray[i].classList.remove('sorting');
thArray[i].classList.add("sorting_asc");
}
else {
thArray[i].classList.remove('sorting');
thArray[i].classList.add("sorting_desc");
}
}
}
}
tharrray-> The array of all row headers(You can just write a jquery selector for this).
sortCol->Column on which sort is clicked (Datatable param iSortCol_0)
sortDir -> Sorting direction (Datatable param sSortDir_0)
I know this is an old thread, but make sure you don't have an .off() somewhere associated with the tables capture group in jQuery. I had a click event that (for some reason) I attached an off function to.. Took me 3 days to find it.

Use object instead of array in datatables

When using datatables, I get 'no data available in table' when using an object instead of array:
var data1 =
{
"status": "success",
"districts": {
"1": {
"district_number": "1",
"district_name": "district one"
},
"2": {
"district_number": "2",
"district_name": "district two"
}
},
"time": "1.109s"
};
var table1 = jQuery("#data_table1").DataTable({
"data": data1.districts,
"aoColumns": [
{ "mData": "district_number" },
{ "mData": "district_name" }
]
});
I can get an array to display in a datatable using mData as follows:
var data2 =
{
"status": "success",
"districts": [
{
"district_number": "1",
"district_name": "district one"
},
{
"district_number": "2",
"district_name": "district two"
}
],
"time": "1.109s"
};
var table2 = jQuery("#data_table2").DataTable({
"data": data2.districts,
"aoColumns": [
{ "mData": "district_number" },
{ "mData": "district_name" }
]
});
https://jsfiddle.net/w93gubLv/
Is there a way to get datatables to utilize the object in the original format, or must I convert the object to an array?
You can write your own function to convert one format to another, for example:
function formatData(data){
var result = [];
for(prop in data){
if(data.hasOwnProperty(prop)){
result.push( data[prop] );
}
}
return result;
}
You can then later use it to pass data to jQuery DataTables as shown below.
var table1 = jQuery("#data_table1").DataTable({
"data": formatData(data1.districts),
"aoColumns": [
{ "mData": "district_number" },
{ "mData": "district_name" }
]
});
See updated jsFiddle for code and demonstration.

dataTables make <tr> clickable to link

I have a dataTables table at http://communitychessclub.com/test.php
My problem is I need to make an entire table row clickable to a link based on a game#. The table lists games and user should click on a row and the actual game loads.
I am unable to understand the previous solutions to this problem. Can somebody please explain this in simple terms?
I previously did this at http://communitychessclub.com/games.php (but that version is too verbose and does disk writes with php echo)
with
echo "<tr onclick=\"location.href='basic.php?game=$game'\" >";
<script>$(document).ready(function() {
$('#cccr').dataTable( {
"ajax": "cccr.json",
"columnDefs": [
{
"targets": [ 0 ],
"visible": false,
}
],
"columns": [
{ "data": "game" },
{ "data": "date" },
{ "data": "event" },
{ "data": "eco" },
{ "data": "white_rating" },
{ "data": "white" },
{ "data": "black_rating" },
{ "data": "black" }
]
} );
} );</script>
"cccr.json" looks like this and is fine:
{
"data": [
{
"game": "5086",
"date": "09/02/2013",
"event": "135th NYS Ch.",
"eco": "B08",
"white": "Jones, Robert",
"white_rating": "2393",
"black": "Spade, Sam",
"black_rating": "2268"
},
...
You can do it this way:
Use fnRowCallback to add a game-id data-attribute to your datatable rows
...
{ "data": "black" }
],
"fnRowCallback": function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
//var id = aData[0];
var id = aData.game;
$(nRow).attr("data-game-id", id);
return nRow;
}
This will give each row in your table a game id attribute e.g:
<tr class="odd" data-game-id="5086">
Then create a javascript listener for the click event and redirect to the game page passing the game id taken from the tr data-attribute:
$('#cccr tbody').on('click', 'tr', function () {
var id = $(this).data("game-id");
window.location = 'basic.php?game=' + id;
}