Setting defaultContent globally across all datatables - javascript

I just updated my Datatable library from 1.10.12 to 1.11.4.
I use datatables extensively in my web app and after this upgrade I keep getting this error: https://datatables.net/manual/tech-notes/4
I understand that this warning basically wants me to set a "defaultContent": "" to my column definition.
The problem is that I would need to update over 200 tables in the webapp to fix the issue.
Is there a way to set this defaultContent:'' globally ?
I have attempted a few things, but the most recent was to extend the defaults in datatables.js with this code
$.extend(true, $.fn.dataTable.defaults, {
columnDefs: [
{
targets:'_all',
defaultContent: "",
},
]
});
The problem with that, I think, is that in my tables I do this:
let columnCount = 0
let table = $("#someTable").DataTable({
data: [],
paging: false,
responsive: true,
sDom: '<"top"B>rt<"bottom"i><"clear">',
columnDefs: [
{
// Order
render: function (data, type, row) {
return row.sortOrder // If this is null or undefined that error shows up
},
targets: columnCount++
defaultContent: '' // I DO NOT want to add this to every single column in every table.
}
],
});
Which overrides the previous definition of the columnDefs.
Similar to this post: datatables default render function for empty cells
So going back to what I am trying to accomplish:
Is there a way to set this defaultContent:'' globally once and have it applied to all columnDefs?

One solution would be to change:
let columnCount = 0
let table = $("#someTable").DataTable({
data: [],
paging: false,
responsive: true,
sDom: '<"top"B>rt<"bottom"i><"clear">',
columnDefs: [
{
// Order
render: function (data, type, row) {
return row.sortOrder // If this is null or undefined that error shows up
},
targets: columnCount++
defaultContent: '' // I DO NOT want to add this to every single column in every table.
}
],
});
to
let columnCount = 0
let table = $("#someTable").DataTable({
data: [],
paging: false,
responsive: true,
sDom: '<"top"B>rt<"bottom"i><"clear">',
columns: [ <----- NOTE THIS CHANGE and no defaultContent
{
// Order
render: function (data, type, row) {
return row.sortOrder
},
targets: columnCount++
}
],
});
and have
$.extend(true, $.fn.dataTable.defaults, {
columnDefs: [
{
targets:'_all',
defaultContent: "",
},
]
});
This would still involve changing part of the datatables but not every single column definition at least.

Related

jQuery Datatables - add rows in a function that returns a Promise

I have a Single Page Application in which I am trying to populate a JQuery Datatable with the results of an AJAX call. The AJAX call returns a Promise.
The code where I define the table and call the AJAX function to populate it is shown below. The data never appears in the table.
if ( ! $.fn.dataTable.isDataTable( '#clients' ) ) {
table = $('#clients').DataTable({
"order": [],
retrieve: true,
"select": true,
select: {
style: 'single'
},
info: false,
lengthChange: false,
ordering: false,
"columns": [
{"data": "name"},
{"data": "dateofbirth"},
{
"data": "id",
"visible": false
}
]
});
clientMaintenance.getClientsForAccount()
.then(function (data) {
table.clear();
table.rows.add(data).draw();
});
I can see that data in getClientsForAccount.then is a JavaScript array, so I don't understand why the data does not appear in the table.
Consider using columnDefs instead of columns. You can find documentation on how to use columnDefshere.

Populate a datatable starting from the second column

I have a datatable that retrieves json data from an api. The first column of the table should only contain a checkbox. However, when retrieving the data it populates the first column as well.
$.getJSON('https://api.myjson.com/bins/o44x', function(json) {
$('#parametrictable').DataTable({
data : json.data,
columns : json.columns,
columnDefs: [ {
orderable: false,
className: 'select-checkbox',
targets: 0
} ],
select: {
style: 'os',
selector: 'td:first-child'
},
order: [[ 1, 'asc' ]]
})
});
Is there any way that I can set that the data should only populate starting from the second column, leaving the first column to only contain the checkbox?
You can fix this issue by updating the api or in your js code just updating the data key value to null for first object in the json.columns array like:
$.getJSON('https://api.myjson.com/bins/o44x', function(json) {
json.columns[0].data = null;
json.columns[0].defaultContent = '';
$('#parametrictable').DataTable({
data: json.data,
columns: json.columns,
.... your rest of code
})
});
EDIT:
I meant what your suggestion only did was hide the data that was overlapping with the checkbox. I don't want it hidden. I want the first column to be, by default, only checkboxes. and the overlapping data should be on the 2nd column.
You can update your API like this to achieve that:
"columns": [
{
"data": null,
"defaultContent": ""
},
{
"data": "DT_RowId",
"title": "Id"
},
{
"data": "supplier",
"title": "supplier"
},
{
"data": "color",
"title": "color"
}
],
Or, you can update your code without modifying your API like:
$.getJSON('https://api.myjson.com/bins/o44x', function(json) {
// Add object for checkbox at first position
json.columns.unshift({"data": null, "defaultContent": ""});
$('#parametrictable').DataTable({
data: json.data,
columns: json.columns,
....your rest of code
})
});

Two DataTables sourced from different APIs on the same page show the same data

I have two DataTables on the same web page with the same number of columns that are sourced from DIFFERENT APIs. If I add the class "grid" to one or the other the table displays with the correct data for that table. However, if I add the class "grid" to both, the data for the first table shows up on BOTH tables.
The class "grid" is a very complex DataTable that involves quite a bit of configuration but here is how "grid" is initialized:
var t = $(".grid").DataTable({
iDisplayLength: 10,
columnDefs: [{
"searchable": false,
"orderable": bOrderBy,
"targets": 0
}],
order: [[0, orderDir]],
ajax: {
url: src,
dataSrc: ""
},
columns: [
{
data: f1
},
{
data: f2
},
{
data: f3
},
{
data: f4
},
{
data: f5,
. . . "blah, blah, blah"
});
t.on('post-body.bs.table', function () {
$('[data-toggle="tooltip"]').tooltip({
container: 'body',
placement: 'top'
});
});
if (autoNum == "Y") {
t.on('order.dt search.dt', function () {
t.column(0, { search: 'applied', order: 'applied' }).nodes().each(function (cell, i) {
cell.innerHTML = i + 1;
});
}).draw();
}
How do I fix this?
Right now, it is applying the same DataTable instance to anything selected in your .grid selector which is why they are coming back the same. If the table options are the same, you can save this into a obj and then pass it to each call. Name the 2 tables with different id's or different classes
var dtOptions = {
iDisplayLength: 10,
columnDefs: [{
"searchable": false,
"orderable": bOrderBy,
"targets": 0
}],
order: [[0, orderDir]],
ajax: {
url: src,
dataSrc: ""
},
columns: [
{
data: f1
},
{
data: f2
},
{
data: f3
},
{
data: f4
},
{
data: f5,
. . . "blah, blah, blah"
};
$("#mytable1).DataTable(dtOptions);
$("#mytable2).DataTable(dtOptions);
You may need to change the ajax src for the 2nd table as you said they are coming from separate api's. You could possibly copy the options object and modify the ajax src if needed.
var dtOptions2= $.extend(true, {}, dtOptions);
dtOptions2.ajax.url = "somthing-else...";
$("#mytable2).DataTable(dtOptions2);

Make edit link on datatable with multiple column values and global search on single/custom column(s)

How to create an edit link with function having multiple parameter from the data columns returned from ajax.
I read about the render callback but it only gets one column value & I need 2.
I need something like the following pseudo code.
"columnDefs": [ {
"targets": [0,1],
"data": "0,1",
"render": function ( data, type, full, meta ) {
return ``
}
} ]
As I'm disabling global search on all column except one. I cannot use the above code that use targets property. I don't know how to achieve this, please guide.
Edit: Complete code
var datatable = $('#datatable').DataTable({
"ajax": "/get_data/",
"processing": true,
"serverSide": true,
"deferRender": true,
"columnDefs": [
{ "searchable": false, "targets": [ 0,2,3,4,5,6,7,8,9,10,11 ] }
]
});
You can access row data using full variable, for example full[0] or full[1].
However instead of generating links in HTML, I would retrieve row data in a click handler as shown below:
$('#example').DataTable({
"columnDefs": [
{
"targets": [0, 1],
"render": function ( data, type, full, meta ) {
return 'Edit';
}
}
],
// ... other options ...
});
$('#example').on('click', '.btn-edit', function(){
// Get row data
var data = $('#example').DataTable().row($(this).closest('tr')).data();
edit(data[0], data[1]);
});
I needed Edit link on first column, so I followed #Gyrocode.com answer and it works great.
I also wanted to use the global search for searching but only on one column. Datatable ColumnDef Documentation gave me the clue so I ended up doing as follows.
Here The complete code:
var datatable = $('#datatable').DataTable({
"ajax": "/get_data/",
"processing": true,
"serverSide": true,
"deferRender": true,
"columnDefs": [
{
"targets": 0,
"render": function ( data, type, full, meta ) {
return 'Edit';
}
},
{ targets: 1, searchable: true },
{ targets: '_all', searchable: false }
]
});

odd datatables behavior when there are no results. 1 works, 1 doesn't

I am seeing this odd thing happen - i'm using datatables to grab dynamic data but the issue that i am having is that one table is applying the 'dataTables_empty' class to the results, the other is not. Any ideas? Screen shots below. Both tables are configured the exact same way in the code.
Code:
function searchOrdersHandler(data) {
if (!ax.Utils.dataSurety(data)) {
return false;
}
if (!ax.theUser.permissions['orders|view']) {
return false;
}
var theData = ax.Orders.addUniqueProductString(data.data.results);
ax.Utils.buildBreadcrumbs($searchBreadcrumbs, [{
link: window.location.hash,
text: "Search"
}, {
link: window.location.hash,
text: data.data.search_label
}], '>');
if (!orderGlobalSearchDTO) {
orderGlobalSearchDTO = $searchOrdersTable.DataTable({
destroy: true,
data: theData,
columns: ordersSearchMap,
autoWidth: false,
paging: false,
dom: 'ft',
searching: false
});
} else {
orderGlobalSearchDTO.clear();
orderGlobalSearchDTO.rows.add(theData);
orderGlobalSearchDTO.draw();
}
ax.Tables.responsify($searchOrdersTable);
SearchPVM.globalOrdersLoading(false);
}; //searchOrdersHandler

Categories