Datatables: custom function inside of fnRowCallback - javascript

Trying to run function inside of fnRowCallback.
jQuery reports this error:
too much recursion
/js/jquery.js
Line: 4
Cannot find this neverending loop.
alert(aData.toSource()); shows array which i'm trying to loop through.
var clientId = 1234;
var reportData = $('#report-data').dataTable({
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "?go=report&do=process&action=get-report",
"fnServerData": function ( sSource, aoData, fnCallback ) {
aoData.push({ "name": "client_id", "value": clientId });
$.getJSON( sSource, aoData, function (json) {
fnCallback(json);
});
},
"fnRowCallback": function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
formatDates(nRow,aData);
},
});
function formatDates(nRow,aData) {
// alert(aData.toSource());
for(i=0; i!=aData.length; i++) {
if (aData[i].match(/^([0-9]{4}-[0-9]{2}-[0-9]{2})T([0-9]{2}:[0-9]{2}):[0-9]{2}\.[0-9]{3}$/gi)) {
reportData.fnUpdate('New Date Format', nRow['_DT_RowIndex'], i);
}
}
}

For each row, fnRowCallback is called, which calls fomatDates, which is calling fnUpdate, which redraws the table, calling fnRowCallback...
EDIT: Thinking about this more, forcing a redraw may cause the recursion problem all over again. Instead, replace the call to fnUpdate in your fnRowCallback to this:
$(nRow).find('td:eq(' + i + ')').text('New Date Format');
This will update the text of the i-th TD element to 'New Date Format', which is what it appears you're wanting to do.

Related

change datatable cell background function

After returning the data for a datatable, I want to be able to change the cell background color based on the cell data using a function called changeCell().
function changeCell(day)
{
if(day == "SPAIN")
{
return $(nTd).css({'background-color': '#33CC33'});
}
if(day == "NEW YORK")
{
return $(nTd).css({'background-color': '#AFD645'});
}
// and so on
}
Here is the datatable (simplified as much as possible):
$.ajax({
url: 'process/getData.php',
type: 'POST',
data: data,
dataType: 'html',
success: function(data, textStatus, jqXHR){
var jsonObject = JSON.parse(data);
var table = $('#example1').DataTable({
"data": jsonObject,
"columns": [
{
"data": "DAY_MON",
"fnCreatedCell": function (nTd, sData, oData, iRow, iCol)
{
changeCell(oData.DAY_MON); // function call here
}
}
]
});
},
error: {
// bunch of error stuff
}
});
However when I call the function, I get the following error:
Uncaught ReferenceError: nTd is not defined
I'm assuming the error is because the function doesn't recognize the nTd, but the nTd is what I need to return back to the datatable.
How can I make this function work?
As nTd is not in the scope of your changeCell function, you have to pass it to it as an argument like other one:
"fnCreatedCell": function (nTd, sData, oData, iRow, iCol) {
changeCell(nTd, oData.DAY_MON);
}
You'd then change the definition of your function to be:
function changeCell(nTd, day) {
// ...
}
I think you can use jQuery Datatable built in function
var dt= $('#example1').DataTable({
'rowCallback': function(row, data, index){
$(row).find('td:eq(1)').css('color', 'black') //1 is index of your td
}
});
see working here

rowData remains on first record after filtering

When using the filter box of a datatable, the rowId remains on the first record, and I cannot figure out why.
Here is the datatable (simplified as much as possible):
$.ajax({
url: 'process/getData.php',
type: 'POST',
data: data,
dataType: 'html',
success: function(data, textStatus, jqXHR){
var jsonObject = JSON.parse(data);
var table = $('#example1').DataTable({
"data": jsonObject,
"columns": [
{
"data": "MONDAY",
"fnCreatedCell": function (nTd, sData, oData, iRow, iCol)
{
$(nTd).html("<span class='checkMon'>+oData.MONDAY+</span>");
},
// columns for each work day
}
],
"paging": false,
"scrollY": 730,
"scrollX": true,
"bDestroy": true,
"stateSave": true,
"autoWidth": true
});
},
error: function(jqHHR, textStatus, errorThrown) {
console.log('fail: '+ errorThrown);
return false;
}
});
Outside of the datatable, I have onclick event handler:
$('#example1').on('click', 'tr > td > .checkMon', function(e)
{
e.preventDefault();
var $dataTable = $('#example1').DataTable();
var tr = $(this).closest('tr');
var data = $dataTable.rows().data();
var rowData = data[tr.index()];
console.log(rowData.UID);
});
Prior to filtering, when I click any cell, the console reads the correct rowData.UID.
The problem is when I filter and click the cell again, the console reads the first row's rowData.UID.
Does anyone see why this is happening and how to fix it?
If what you want to achieve is simply log into the console UID property of the object that sourced the row that holds the <span> you've clicked, following approach should work:
$('#example1').on('click', '.checkMon', function(e)
{
e.preventDefault();
const dataTable = $('#example1').DataTable();
const rowData = dataTable.row($(this).closest('tr')).data();
console.log(rowData.UID);
});
Also, consider using ajax option. With that you won't need to waste performance destroying/re-creating your table and that will make your code cleaner and safer.

Ajax error on datatable initialisation on table within modal

I have a modal with a search box within it, which when the search button is hit, has an ajax call which goes to the controller, which then returns a table of results, which is then put into a div. Like so:
$.ajax({
url: url,
data: JSON.stringify(viewModel),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
cache: false,
type: "POST",
success: function (result) {
if (result.success === true) {
$("#searchResultsPlaceHolder").show();
$("#searchResultsPlaceHolder").html(result.view, function() {
var noOfRows = $('#searchResultsTable tr').length;
if (noOfRows > 1) {
loadSearchDatatable();
}
});
}
},
error: function (responseText, textStatus, errorThrown) {
alert('Error - ' + errorThrown);
}
});
All that is fine, and works perfectly up until I try to make it a datatable. If I take out the lines
$("#searchResultsPlaceHolder").html(result.view, function() {
var noOfRows = $('#searchResultsTable tr').length;
if (noOfRows > 1) {
loadSearchDatatable();
}
});
and just have
$("#searchResultsPlaceHolder").html(result.view)
it works fine, it gives me a table with my results. But as this is in a modal, and the returned results may get quite lengthy, I want to use a datatable to implement pagination and sorting. But whenever I apply the loadSearchDatatable function to the table after the div is populated with the returned html, I get the error:
table id=searchResultsTable - Ajax error
The datatable actually appears, with the sort buttons and paging buttons present, but none of them do anything, and the table is longer than the length I specified (5). Here is my datatable function:
function loadSearchDatatable() {
$('#searchResultsTable').dataTable({
ajax: "data.json",
"bLengthChange": false,
'iDisplayLength': 5,
"bSort": true,
"sPaginationType": "full_numbers",
"bFilter": false,
"sDom": 'ft<"bottom"ilp>',
"bDestroy": false,
"aaSorting": [[0, "asc"]]
});
};
Does anyone have any idea how to fix this error?
Use the code below instead:
$("#searchResultsPlaceHolder").html(result.view);
var noOfRows = $('#searchResultsTable tr').length;
if (noOfRows > 1) {
loadSearchDatatable();
}
Also remove ajax: "data.json", in your function loadSearchDatatable().

Datatables, change AJAX data ( not with elements )

I have a Datatable which is getting populated by AJAX. All is good but i want to have some shortcuts to request data from the server. Problem is how can i change the data i'm sending on the fly ? I know i can create an element <input> or something and it can get the value from that, but i was hoping i could change the data once something is clicked.
var Table = $('#table').DataTable({
"ajax": {
"type" : "POST",
"url": "url",
"data": function ( d ) {
d.cmd = "offline";
}
},
});
This works fine and passes the cmd as offline back to the server.
How can i change that value on click before the ajax.reload is called.
$('#online_btn').on( 'click', function () {
Table.ajax.reload();
} );
Using this
$('#online_btn').on( 'click', function () {
var d = [];
d.cmd = "online";
Table.ajax.data(d);
Table.ajax.reload();
} );
Gives back an ajax.data is not a function error
You could modify an object and use $.extend() to merge within the data function
var myData ={};
var Table = $('#table').DataTable({
"ajax": {
"type" : "POST",
"url": "url",
"data": function ( d ) {
return $.extend(d, myData);
}
},
});
$('#online_btn').on( 'click', function () {
myData.cmd = "online";
Table.ajax.reload();
});
Use jquery ajax beforesend object.
$.ajax({
url: "http://fiddle.jshell.net/favicon.png",
beforeSend: function( xhr ) {
//update your value here
}
})
source: jquery documentation
beforeSend
Type: Function( jqXHR jqXHR, PlainObject settings )
A pre-request callback function that can be used to modify the jqXHR (in jQuery 1.4.x, XMLHTTPRequest) object before it is sent. Use this to set custom headers, etc. The jqXHR and settings objects are passed as arguments. This is an Ajax Event. Returning false in the beforeSend function will cancel the request. As of jQuery 1.5, the beforeSend option will be called regardless of the type of request.
I do this in 2021:
function customSearch(){
let t = JSON.parse(window.filter);
t["custom-field"] = $('input[name="custom-field"]').val() || "";
window.filter = JSON.stringify(t);
return window.filter;
}
const table = $('#table').DataTable({
ajax:{
url:"my-wonderful-url.json",
type:"POST",
data: function(d) {
const t = customSearch();
return Object.assign(d, {filter:t});
},
error:function(e){console.log(e);},
});
$('input[name="custom-field"]').on('keyup', function(e){
table.ajax.reload(null, false);
});

Using DataTables Plugin with GET requests to pass requestbody

I have a javascript function fetchGroups() that builds a paged data table using the datatable plugin. The request being passed in is a GET request. I need to pass a fetchMemberGroups object along with the request. I tried sending the request with the request body. But it doesn't seem to work and keeps throwing a 500-Internal Server Error. I also don't believe I can pass a request body with a GET. I then tried to pass the fetchMemberGroupsobject along with the URL by appending a #PathParam annotation on the service method. Could someone tell me how do I pass this object to the service without changing the type of the service to POST or PUT.
function fetchGroups() {
var fetchMemberGroups = new Object();
fetchMemberGroups.sEcho = 0;
$("#displayGroupsTable").dataTable({
"bServerSide": true,
"sAjaxSource":"api/groupService/groups",
"bProcessing": true,
"bJQueryUI": true,
"bRetrieve": true,
"fnServerData": function ( sSource, aoData, fnCallback, oSettings ) {
fetchMemberGroups.iDisplayStart=oSettings._iDisplayStart;
fetchMemberGroups.iDisplayLength=oSettings._iDisplayLength;
fetchMemberGroups.sEcho=fetchMemberGroups.sEcho+1;
oSettings.jqXHR=$.ajax( {
"contentType" : 'application/json',
"dataType": 'json',
"type": "GET",
"url": sSource,
"data": JSON.stringify(fetchMemberGroups),
"success": fnCallback
});},
"aoColumns": [
{ "mData": "groupName" },
{ "mData": "numberOfMembers"},
{ "mData": "distinguishedName"}
]
});
}
The server side code:
#GET
#Path("groups")
#Produces({ MediaType.APPLICATION_JSON })
#Consumes({MediaType.APPLICATION_JSON})
public Response getGroups(#Context HttpServletRequest request, PagingObject fetchGroupsObject) {
}
EDIT:
you should not be using the oTable api to set your parameters to send to the server...because oSettings doesnt exist yet, oTable hasnt been created so there's no oSettings
you should not have to specify sEcho, iDisplayStart, iDisplayLength those are automatically created in a server side implementation by the framework
what you do need to do is evaluate them in your query to get your result limit, ect
if you could i would suggest trying the following, and see if it returns anything in the network inspector of firebug/chrome tools
"fnServerData": function ( sSource, aoData, fnCallback ) {
$.getJSON( sSource, aoData, function (json) {
fnCallback(json);
});
Previous
Im pretty sure your fnServerData is off, or at least its unlike anything ive seen
Typically i do something similar to this, where lastname is an additional parameter, and as getJSON you know its a get:
"fnServerData": function ( sSource, aoData, fnCallback ) {
aoData.push( { "name" : "LastName", "value" : "$('#LastName').val()" } );
$.getJSON( sSource, aoData, function (json) {
fnCallback(json);
});
The 500 error also sems like the url doesnt exist, have you tried opening the url on its own rather than from ajax?

Categories

Resources