Column Visibility is not restored from a saved state via stateLoadCallback - datatables

I have added the Column Visibility button to choose to show or hide certain columns. I'm saving the state in a database, I call the stateSaveCallback function via a click on a button.
I cant find documentation about retrieving data this way, so I just link to the page and pass variables to get the data back from the database, and then load that using stateLoadCallback.
Now all this works fine, EXCEPT the column visibility is not restored. It is in the JSON data being returned though.
Here is my full code:
$(document).ready(function() {
$.extend( jQuery.fn.dataTableExt.oSort, {
"date-uk-pre": function (a){
return parseInt(moment(a, "DD/MM/YYYY").format("X"), 10);
},
"date-uk-asc": function (a, b) {
return a - b;
},
"date-uk-desc": function (a, b) {
return b - a;
}
});
var edit_date_col_num = $('th:contains("Edit Date")').index();
var entry_date_col_num = $('th:contains("Entry Date")').index();
var table = $('.mainTable').DataTable( {
pageLength: 50,
colReorder: true,
stateSave: true,
columnDefs: [
{ "type": "date-uk", targets: [ edit_date_col_num, entry_date_col_num ] }
],
dom: 'Blfrtip',
buttons: [
'copy', 'csv', 'excel', 'print',
{
extend: 'colvis',
collectionLayout: 'fixed four-column',
postfixButtons: [ 'colvisRestore' ]
}
],
<?php
$id = $this->input->get('id');
$action = $this->input->get('action');
if(isset($action) && $action == 'load' && isset($id) && $id != '') :
?>
"stateLoadCallback": function (settings) {
var o;
// Send an Ajax request to the server to get the data. Note that
// this is a synchronous request since the data is expected back from the
// function
$.ajax( {
"url": EE.BASE + "&C=addons_modules&M=show_module_cp&module=ion&method=state_save&action=load&id=<?php echo $id;?>",
"async": false,
"dataType": "json",
"success": function (response) {
response = JSON.parse(response);
o = response;
}
});
return o;
},
<?php
endif;
?>
initComplete: function (settings) {
this.api().columns().every( function () {
var column = this;
var select = $('<select><option value=""></option></select>')
.appendTo( $(column.footer()).empty() )
.on( 'change', function () {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column
.search( val ? '^'+val+'$' : '', true, false )
.draw();
} );
column.data().unique().sort().each( function ( d, j ) {
select.append( '<option value="'+d+'">'+d+'</option>' )
} );
} );
// Need to re-apply the selection to the select dropdowns
var cols = settings.aoPreSearchCols;
for (var i = 0; i < cols.length; i++)
{
var value = cols[i].sSearch;
if (value.length > 0)
{
value = value.replace("^", "").replace("$","");
console.log(value);
$("tfoot select").eq(i).val(value);
}
}
},
} );
// Save a datatables state by clicking the save button
$( ".save_state" ).click(function(e) {
e.preventDefault();
table.destroy();
$('.mainTable').DataTable( {
colReorder: true,
stateSave: true,
"stateSaveCallback": function (settings, data) {
var save_name = $('.save_name').val();
// Send an Ajax request to the server with the state object
$.ajax( {
"url": EE.BASE + "&C=addons_modules&M=show_module_cp&module=ion&method=state_save&action=save&save_name="+save_name,
"data": data,
"dataType": "json",
"type": "POST",
"success": function (response)
{
//console.log(response);
}
} );
},
});
//table.state.save();
window.location.replace(EE.BASE + "&C=addons_modules&M=show_module_cp&module=ion&method=applications");
});
$( ".clear_state" ).click(function(e) {
e.preventDefault();
table.state.clear();
window.location.replace(EE.BASE + "&C=addons_modules&M=show_module_cp&module=ion&method=applications");
});
} );
Here is the saved JSON with several visible false in the beginning (which are visible once loaded):
{"time":"1449338856556","start":"0","length":"50","order":[["0","asc"]],"search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"},"columns":[{"visible":"false","search":{"search":"","smart":"false","regex":"true","caseInsensitive":"true"}},{"visible":"false","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"false","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"false","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"false","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}},{"visible":"true","search":{"search":"","smart":"true","regex":"false","caseInsensitive":"true"}}],"ColReorder":["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52","53","54","55","56","57","58","59","60","61","62","63","64","65","66","67","68","69","70"]}
Thanks

In my case datatables rejects old data according to "stateDuration" and "time" properties..
Solution: ignore state duration
"stateSave": true,
"stateDuration": -1,
Above case:
"visible":"false" may should be "visible":false

After a while of debugging this myself here's what worked for me..
This issue is that all the values in your JSON are strings and they need to be of correct datatypes for the datatables plugin.
Within the "stateSaveCallback" ajax request to save your state I did the following to the json string and then it saved all the values properly which then loaded the state as it should.
"stateSaveCallback": function (settings, data) {
var save_name = $('.save_name').val();
// Send an Ajax request to the server with the state object
$.ajax( {
"url": EE.BASE + "&C=addons_modules&M=show_module_cp&module=ion&method=state_save&action=save&save_name="+save_name,
//"data": data,
"data": JSON.stringify(data), // change to this..
"dataType": "json",
"type": "POST",
"success": function (response)
{
//console.log(response);
}
} );
},

Related

How to update data after ajax reload using initComplete callback for DataTables when using ajax source data?

I’m using a select object to trigger an ajax reload for a DataTable.
I need to add individual column searching with select inputs for a given column (not for every column) but the select is filled with the previous ajax response.
How can I update the data that the initCompleteFunction callback uses to fill the select input in the individual column searching?
// this is the select that triggers the ajax.reload
$('#proveedor').on('change', function () {
$datatable
.DataTable()
.ajax
.reload(initCompleteFunction, false);
});
// this is my initCompleteFunction callback
function initCompleteFunction(settings, json){
var api = new $.fn.dataTable.Api( settings );
api.columns().every( function () {
var column = this;
if ($(column.header()).hasClass('select')) {
var select = $('<select><option value="">' + $(column.header()).html() + '</option></select>')
.appendTo( $(column.footer()).empty() )
.on( 'change', function () {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column
.search( val ? '^'+val+'$' : '', true, false )
.draw();
return false;
} );
//this is the part that keeps previous data insted of the new one from the ajax reload
column.data().unique().sort().each( function ( d, j ) {
select.append( '<option value="'+d+'">'+d+'</option>' );
} );
}
});
}
// and this is how I’m setting the DataTable
var $datatable = $('#table_materiales');
$datatable
.on('xhr.dt', function ( e, settings, json, xhr ) {
initCompleteFunction(settings, json);
})
.DataTable({
"ajax": {
"url": "http://my_endpoint",
"dataSrc": "",
"type": "POST",
"data": {
id_proveedor: function () {
return $('#proveedor').val(); // to get the value in the provider’s filter (select)
}
}
},
"columns": [
{
data: 'row_num'
},{
className: "select",
data: 'material'
},
// here goes the rest of the column definitions
],
"paging": false,
'columnDefs': [
{
'targets': 0,
'checkboxes': {
'selectRow': true
}
}
],
'select': {
'style': 'multi'
},
'order': [
[3, 'asc']
],
"createdRow": function (row, data, dataIndex) {
$(row).attr('data-id-material', data.id_material);
$(row).attr('data-pedido_sugerido', data.pedido_sugerido);
$(row).attr('id', 'id_' + data.row_num);
if(data['status_de_tiempo']=='FUERA'){
$(row).addClass('redClass');
}
},
});
During research I found that the xhr.dt event is triggered before the ajax.reload() is completed so the data keeps outdated when the select for the individual column search is populated. See this reference
User grozni posted this on April, 2019:
I have used console logs and was able to confirm that the event fires before the XHR event concludes, and does not pull the latest JSON. I used XHR tracking where I could to get around it but it's still really inconvenient and complicating matters alot. I need to be able to do certain things after the data is loaded and drawn. Perhaps it's worthy of a bug report
I found this post (See here) where user conangithub needed to
count DataTables item after I reload DataTable successfully
User lovecoding-git suggested this approach:
table= $('#example').DataTable();
$('#example').on('draw.dt', function() {
console.log(table.ajax.json().recordsTotal);
});
So, for my own issue, instead of
.on('xhr.dt', function ( e, settings, json, xhr ) {
initCompleteFunction(settings, json);
})
I wrote
.on('draw.dt', function ( e, settings, json, xhr ) {
initCompleteFunction(settings, json);
})
Et voilà.
I got the needed solution.

Zapier Dynamic Custom Fields

I am trying to offer custom fields from a platform as input fields I have done this in the past with another platform and with Zapiers older UI. It does not seem to be that simple now.
const options = {
url: 'https://edapi.campaigner.com/v1/Database',
method: 'GET',
headers: {
'X-API-KEY': bundle.authData.ApiKey
},
params: {
'ApiKey': bundle.authData.ApiKey
}
};
return z.request(options).then((response) => {
response.throwForStatus();
const results = response.json;
const col = results.DatabaseColumns.filter((item) => item.IsCustom).map((item) => {
return {
...item,
id: item["ColumnName"],
};
});
return col});
That is what I am trying to use for the Action. I am using this same does for a Trigger and it works there, but not as Dynamic Field Option along with other standard inputs.
Not sure if I need to tweak the code or if I can invoke the data that the Trigger would pull?
Here is the visual of the fields, but I need it to pull and offer the custom fields. This would be like favorite color, etc.
Image of Zap
Any help is appreciated.
I was able to use this code:
// Configure a request to an endpoint of your api that
// returns custom field meta data for the authenticated
// user. Don't forget to congigure authentication!
const options = {
url: 'https://edapi.campaigner.com/v1/Database',
method: 'GET',
headers: {
'X-API-KEY': bundle.authData.ApiKey
},
params: {
'ApiKey': bundle.authData.ApiKey
}
};
return z.request(options).then((response) => {
response.throwForStatus();
const results = response.json;
var col = results.DatabaseColumns.filter((item) => item.IsCustom).map((item) => {
return {
...item,
key: item["ColumnName"],
value: item["ColumnName"]
};
});
//var col = col.filter(items => ['FirstName', 'LastName'].indexOf(items) >= 0 )
for (var i = col.length; i--;) {
if (col[i].key === 'FirstName' || col[i].key === 'LastName' ) {
col.splice(i, 1);
}
}
return col});
/*
return [
{
"key": "FirstName",
"value":"First Name"
},
{
"key": "LastName",
"value": "Last Name"
},
{
"key": "Test",
"value": "Test 2"
},
*/

Get value and pass to parameter datables

So I have datetimepicker. And I have datatable like the following code
var table = $("#tbllogvisitor");
var target = table.attr('data-table');
var date = $("#datetimepicker3").data("date");
var oTable = table.on( 'processing.dt', function ( e, settings, processing ){
if (processing) {
$(this).find('tbody').addClass('load1 csspinner');
} else{
$(this).find('tbody').removeClass('load1 csspinner');
};
}).DataTable({
"bServerSide": true,
"paging": false,
"filter": false,
"scrollCollapse": true,
"ordering": false,
"ajax": {
"url" : "../ajax/datatable",
"type": "POST",
"data" :{
target: function() { return target },
tanggal: function() { return date }
}
}
});
Well is working, and then I wanna trigger datetimepicter if I'm changing my datetimepicter value with the following code :
$("#datetimepicker3").on("dp.change", function (e) {
oTable.ajax.reload();
});
But the paramater variable of datetimepicker still not change at all, still same at first time. How do Ii pass my value datetimepicker and reload the datatable?
Sorry for my bad english.

Jquery Datatables expand row and get detail via Ajax

Is it possible to get the detail for each row through Ajax?
I found a starting point here:
http://datatables.net/release-datatables/examples/api/row_details.html
but it doesn't use ajax.
I'm thinking about modifying fnFormatDetails() function and place the ajax call there.
But i'm looking for another better answer.
Thanks.
It's very simple. All you have to do is put your details in a separate field within the "data" array:
E.g. your JSON might look like as follows:
{
"draw": "${drawId}",
"recordsTotal": "${totalRecords}",
"recordsFiltered": "${filteredRecords}",
"data": [
{
"empName": "${employee.name}",
"empNumber": "${employee.number}",
"empEmail": "${employee.email}",
"extraDetails" : [
["${employee.salary}", "${employee.title}"]
]
}
]
}
Then in your javascript, you can simply access this extra details by using JavaScript arrays. E.g.
var row = employeeTable.row( tr );
var rowData = row.data();
alert(rowData.extraDetails[0][0]);
alert(rowData.extraDetails[0][1]);
You need not to go for ajax if you have the data in your row.
Try oTable.fnGetData(rowIndexor|trNode)
you can try this and it will work.
First: create your datatable.
var table = $('#myTable').DataTable( {
ajax: '/api/staff',
columns: [
{
className: 'details-control',
orderable: false,
data: null,
defaultContent: ''
},
{ data: "name" },
{ data: "position" },
{ data: "office" },
{ data: "salary" }
],
order: [[1, 'asc']] } );
Second: Event handlers
$('#myTable tbody').on('click', 'td.details-control', function () {
var tr = $(this).closest('tr');
var row = table.row( tr );
if ( row.child.isShown() ) {
row.child.hide();
tr.removeClass('shown');
}
else {
row.child( format(row.data()) ).show();
tr.addClass('shown');
} } );
Third: Ajax request and formatting the response
function format ( rowData ) {
var div = $('<div/>')
.addClass( 'loading' )
.text( 'Loading...' );
$.ajax( {
url: '/api/staff/details',
data: {
name: rowData.name
},
dataType: 'json',
success: function ( json ) {
div
.html( json.html )
.removeClass( 'loading' );
}
} );
return div; }
you can pass any row argument to format method.
Check This For More Details

Jeditable + Datatables + Server Side Processing

I have this piece of code...
$(document).ready(function() {
var oTable = $('#example').dataTable( {
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "../listagem/listar_manuais.php",
"sPaginationType": "full_numbers",
"fnDrawCallback": function () {
$('td', this.fnGetNodes()).editable( 'update.php', {
"callback": function( sValue, y ) {
var aPos = oTable.fnGetPosition( this );
oTable.fnUpdate( sValue, aPos[0], aPos[1] );
},
"submitdata": function ( value, settings ) {
return { "row_id": this.parentNode.getAttribute('id') };
},
"height": "14px"
} );
}
});
} );
What it does is the server side search of Datatables...
My problem, is that i don't kno what to do from here, to get the Jeditable functional with the server side processing...
Can anyone help? :s
The values will be in the HTTP Request object in your update.php. Your updated value is in "value", row_id in "row_id" according to your code above.