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
Related
I have this custom made jQuery plugin, whenever I called it in my script, the option parameter row cannot access the variable or data defined on my script.
JQuery Plugin:
{
$.fn.dbGrid = function (options) {
var settings= $.extend({
read: function () { },
row:""
}, options)
settings.read.call(this)
//console.log(settings.row)
//It ouputs nothing
}
Usage on my Script:
var rows;
function onSuccess(data) {
rows = data;
}
function populateTable() {
$("#container").dbGrid({
read: function () {
$.ajax({
url: "some url",
success: onSuccess,
dataType: "json",
async: false,
type: "GET"
});
},
row:rows
//here the option `row` can not access my `rows` defined in my script, thats why it cannot yield result in my plugin whenever I do console.log
})
//console.log("Row in Base script" + rows);
//Here it outputs the result I want which is data from the function onSuccess
}
populateTable();
}
I use the following code to generate jquery datatables with data returned from SharePoint Online JSON on AJAX call. As My SPO list has over 50K rows and SPO has a 5000 view threshold limit, i make multiple ajax calls with REST API multiple date range filters and concat the results. The concatenated results are then passed as data source for the datatables plugin.
Kindly assist to shorten the following code for year variables and make the same to dynamically enter date ranges to make multiple AJAX calls. I'm guessing the process is to first read current year, generate first and last dates for current year, and then create new variables in descending order till 2005.
var results;
var allResults = [];
$(document).ready(function () {
load();
});
function load() {
var year2021 = $.ajax({
url: "SPO_Site/_api/web/lists/getbytitle('SPO_List')/items?$top=5000&$select=*,EncodedAbsUrl&$filter=(Date%20ge%20datetime%272020-12-31T00:00:00.000Z%27)%20and%20(Date%20le%20datetime%272021-12-31T00:00:00.000Z%27)",
type: "GET", dataType: "json", headers: {"accept": "application/json;odata=verbose"},
success: mySuccHandler, error: myErrHandler});
var year2020 = $.ajax({
url: "SPO_Site/_api/web/lists/getbytitle('SPO_List')/items?$top=5000&$select=*,EncodedAbsUrl&$filter=(Date%20ge%20datetime%272019-12-31T00:00:00.000Z%27)%20and%20(Date%20le%20datetime%272020-12-31T00:00:00.000Z%27)",
type: "GET", dataType: "json", headers: {"accept": "application/json;odata=verbose"},
success: mySuccHandler, error: myErrHandler});
.
.
.
.
.
var year2005 = $.ajax({
url: "SPO_Site/_api/web/lists/getbytitle('SPO_List')/items?$top=5000&$select=*,EncodedAbsUrl&$filter=(Date%20ge%20datetime%272004-12-31T00:00:00.000Z%27)%20and%20(Date%20le%20datetime%272005-12-31T00:00:00.000Z%27)",
type: "GET", dataType: "json", headers: {"accept": "application/json;odata=verbose"},
success: mySuccHandler, error: myErrHandler});
function mySuccHandler(a) {
results = a.d.results;
if (allResults.length > 0)
allResults = allResults.concat(results);
else
allResults = results;
}
function myErrHandler(data, errorCode, errorMessage) {
console.log("Could not complete call: " + errorMessage);
};
$.when(year2021, year2020, year2019, year2018, year2017, year2016, year2015, year2014, year2013, year2012, year2011, year2010, year2009, year2008, year2007, year2006, year2005).done(function(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17){
$('#table_id').DataTable({
data:allResults,
dom: 'Bfrtip',
columns: [
{ data: "Reg" },
{ data: "EncodedAbsUrl",
"render": function (data, type, full)
{return 'View';}
}
]
});
});
};
When your find yourself copy-pasting code, stop immediately and write a function and a loop.
When you find yourself copy-pasting code 15 times, you should have stopped 14 times ago to write a function and a loop.
The function:
function getItemsByYear(year, topRows=5000) {
return $.ajax({
type: "GET",
headers: {
Accept: "application/json;odata=verbose"
},
url: "SPO_Site/_api/web/lists/getbytitle('SPO_List')/items?" + $.param({
$top: topRows,
$select: '*,EncodedAbsUrl',
$filter: `(Date ge datetime'${year}-01-01T00:00:00.000Z') and (Date lt datetime'${year + 1}-01-01T00:00:00.000Z')`
}),
})
.then(function (response) {
return response.d.results;
})
.fail(function (data, errorCode, errorMessage) {
console.log("Could not complete call: " + errorMessage);
});
}
The loop:
$(function () {
let currentYear = (new Date()).getFullYear(),
requests = [];
for (let counter = 0; counter < 15; counter++) {
requests.push(getItemsByYear(currentYear - counter));
}
$.when.apply($, requests).done(function (itemsByYear) {
$('#table_id').DataTable({
data: itemsByYear.flat(),
dom: 'Bfrtip',
columns: [
{ data: "Reg" },
{ data: "EncodedAbsUrl", "render": function (data, type, full)
{return 'View';}
}
]
});
});
});
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.
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);
});
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.