DataTables - Dynamic Columns From Ajax Data Source? - php

I am trying to get DataTables to read the column names from an AJAX data source but it seems that there must be something that I must be missing here.
I made a fiddle fiddle in which I can manually define the data and columns that are being used by the table.
The table is declared in the HTML and there is no no need to define the column names (<thead>..</thead>):
<table id="example" class="display table table-striped table-bordered"
cellspacing="0" width="100%"></table>
In the JS we manually define the data:
var data = [
[ "Row 1 - Field 1", "Row 1 - Field 2", "Row 1 - Field 3" ],
[ "Row 2 - Field 1", "Row 2 - Field 2", "Row 2 - Field 3" ],
];
Then manually define the column names or titles:
var columns = [
{ "title":"One" },
{ "title":"Two" },
{ "title":"Three" }
];
Then when we initialise the table we simply pass the previously declared information across for DataTables to use:
$(document).ready(function() {
$('#example').DataTable( {
dom: "Bfrtip",
data: data,
columns: columns
});
});
Which results in:
Now my question is how would I get this to work if the data is included in the AJAX server side response?
I have tried this in various ways and forms but nothing really seems to work out here and I am battling to find relative documentation on this.
For example if the server side processing sent back a JSON response which includes the column names at the end:
{
"data": [
{
"id": "1",
"One": "Row 1 - Field 1",
"Two": "Row 1 - Field 2",
"Three": "Row 1 - Field 3"
},
{
"id": "2",
"One": "Row 2 - Field 1",
"Two": "Row 2 - Field 2",
"Three": "Row 2 - Field 3"
}
],
"options": [],
"files": [],
"columns": [
{
"title": "One",
"data": "One"
},
{
"title": "Two",
"data": "Two"
},
{
"title": "Three",
"data": "Three"
}
]
}
Given this is the response, I tried to configure DataTables to use an AJAX data source for the row information as follows:
$(document).ready(function() {
$('#example').DataTable( {
dom: "Bfrtip",
"ajax": '/test.php',
columns: columns
});
});
But obviously columns is undefined here.
So I get the column data before hand:
function getPromise() {
var deferred = $.Deferred();
var dataUrl = document.location.origin+'/text.php';
$.getJSON(dataUrl, function(jsondata) {
setTimeout(function() {
deferred.resolve(jsondata);
}, 0);
}).fail(function( jqxhr, textStatus, error ) {
// ********* FAILED
var err = textStatus + ", " + error;
console.log( "Request Failed: " + err );
});
return deferred.promise();
}
// Get the columns
getPromise().done(function(jsondata) {
columns = jsondata.columns;
console.log(columns);
});
And pass it to DataTables as above. But this time all I get when running the example is an error in the console saying TypeError: p is undefined.
So then how could I make use of the dynamically generated columns that are being returned within the server side response? Is there not a simpler way to achieve this?
EDIT:
DataTables Editor code for server side processing / to generate the JSON response mentioned above:
<?php
// DataTables PHP library
require_once '/path/to/DataTables.php';
// Alias Editor classes so they are easy to use
use
DataTables\Editor,
DataTables\Editor\Field,
DataTables\Editor\Format,
DataTables\Editor\Mjoin,
DataTables\Editor\Upload,
DataTables\Editor\Validate;
// Build our Editor instance and process the data coming from _POST
$out = Editor::inst( $db, 'example' )
->fields(
Field::inst( 'id' )->set(false),
Field::inst( '`One`' )->validator( 'Validate::notEmpty' ),
Field::inst( '`Two`' )->validator( 'Validate::notEmpty' ),
Field::inst( '`Three`' )->validator( 'Validate::notEmpty' )
)
->process( $_POST )
->data();
// On 'read' remove the DT_RowId property so we can see fully how the `idSrc`
// option works on the client-side.
if ( Editor::action( $_POST ) === Editor::ACTION_READ ) {
for ( $i=0, $ien=count($out['data']) ; $i<$ien ; $i++ ) {
unset( $out['data'][$i]['DT_RowId'] );
}
}
// Create the thead data
if (count ($out) > 0) {
$columns = array();
foreach ($out['data'][0] as $column=>$relativeValue) {
// Add all but the id value
if ($column !== 'id') {
// Add this column name
$columns[] = array(
"title"=>$column,
"data"=>$column
);
}
}
}
// Add the the thead data to the ajax response
$out['columns'] = $columns;
// Send the data back to the client
echo json_encode( $out );

If you don't use the built in DataTables ajax it should be easy enough given the structure of your data:
$(document).ready(function() {
$.ajax({
type: 'POST',
dataType: 'json',
url: '/echo/json/',
data: {
json: JSON.stringify(jsonData)
},
success: function(d) {
$('#example').DataTable({
dom: "Bfrtip",
data: d.data,
columns: d.columns
});
}
});
});
Like this JSFiddle, you're limited then to loading all the data at once but that shouldn't be a huge issue... unless you alter it get the columns from the initial ajax call and once the DataTable is initiated then add the built-in ajax - I've not tried this though...

You must create the table in html without header
<table id="tablaListadoExpediciones" class="table table-bordered table-striped dt-responsive"> </table>
Now you have to generate the columns array dynamically. In this way, the columns will always be generated automatically even if the AJAX response varies over time.
function PintarTablaDinamicamente(datos) {//object "datos" comes from AJAX response
//I take the keys of the object as columns of the table
var arrColumnas = Object.keys(datos[0])
////In case you wanted to hide a column
//var indiceColumna = arrColumnas.indexOf("nameOfTheColumnToHide")
//if (indiceColumna !== -1) {
// arrColumnas.splice(indiceColumna, 1)
//}
var columns = []
//columns must be in JSON format-->{data:'keyToSearchInJSON',title:'columnTitle'}
for (var i in arrColumnas) {
//if (arrColumnas[i] == "SELECCIONAR") { //if you want to add a checkbox in one colunm (for example column named SELECT
// columns.push({
// data: null,
// defaultContent: '',
// className: 'select-checkbox',
// orderable: false
// });
//} else {
columns.push({ data: arrColumnas[i], title: arrColumnas[i] });
//}
}
tabla = $('#tablaListadoExpediciones').DataTable({
dom: "Blfrtip",
data: datos,
//order: [[0, 'desc']],
"pageLength": 25,
"scrollX": true,
columns: columns
,
buttons: [
{
extend: 'copy'
},
{
extend: 'excel'
},
{
extend: 'print'
}
],
//select: {
// style: 'os',
// selector: 'td:first-child'
//}
});
}

Related

Change td type in ajax-loaded datatable [duplicate]

I am trying to make a column as hyperlink with datatable but no success.
function successCallback(responseObj){
$(document).ready(function() {
$('#example').dataTable( {
"data":responseObj ,
"bDestroy": true,
"deferRender": true ,
"columns": [
{ "data": "infomation" },
{ "data": "weblink" },
]
} );
} );
}
I need the weblink to display the link and be an hyperlink in that column so users can click and be redirected to another page. I looked into render but with less information there on links, i can't succeed to do it.
I also looked into this example but it wasn't very helpful.
Use columns.render API method to dynamically produce content for a cell.
$('#example').dataTable({
"data": responseObj,
"columns": [
{ "data": "information" },
{
"data": "weblink",
"render": function(data, type, row, meta){
if(type === 'display'){
data = '' + data + '';
}
return data;
}
}
]
});
See this example for code and demonstration.
If you are looking to add link based on other column data then can use the below approach.
$('#example').dataTable({
"data": responseObj,
"columns": [
{ "data": "information" },
{
"data": "weblink",
"render": function(data, type, row, meta){
if(type === 'display'){
data = '' + data + '';
}
return data;
}
}
]
});
I have just changed the render function. data refers to only current column data, while row object refers to entire row of data. Hence we can use this to get any other data for that row.
$('#example').dataTable( {
"columnDefs": [ {
"targets": 0,
"data": "download_link",
"render": function ( data, type, full, meta ) {
return 'Download';
}
} ]
} );
From the documentation. It is quite clear and straightforward to me, what is it specifically that you do do not understand? What errors do you see?
For a more complete example, see here
in my example I make the column cell fully clickable and not just the text inside the column. I think it will be useful for someone. use bootsrap 5
$(document).ready(function() {
$('#datatable').DataTable({
processing: true,
serverSide: true,
ajax: '{!! route('get.profiles') !!}',
columns: [
{
data: 'id',
name: 'id',
render : function(data, type, row, meta) {return'<a class=" d-inline-block fw-normal w-100 h-100 pe-auto" href="profiles/edit/' + row.id + '">' + row.id + '</a>';},
},
{
data: 'name',
name: 'name',
render : function(data, type, row, meta) {return'<a class="d-inline-block fw-normal w-100 h-100 pe-auto" href="profiles/edit/' + row.id + '">' + row.name + '</a>';},
},
]
});
});
in your css file add
td{
height: 100%;
overflow: visible;
}

Set column type as text in DataTable export

I need to set a column as type text in Excel export from DataTable. All columns are in 'General' mode, so if data from a cell is datelike (2020-11-01 e.g.), Excel trats it like a date and I need it to be a string. This is my code regarding the table.
<script>
$(document).ready( function () {
var groupColumn = 0;
var table = $('#Table1').DataTable( {
"paging": true,
"autoWidth": false,
"info": false,
language: {
search: "_INPUT_",
searchPlaceholder: "Filtra risultati",
},
dom: 'Bfrtip',
buttons: [
{
text: 'Esporta dati',
title: '',
header: true,
extend: 'excel',
orientation: 'landscape',
pageSize: 'LEGAL'
},
],
select: true,
} );
} );
</script>
There is a way to force DataTable to set my third column as TEXT?
You should try:
// (...)
buttons: [
{
extend: 'excelHtml5',
title: "Your Report Name",
exportOptions: {
columns: ':visible',
},
customize: function (xlsx, data) {
var sheet = xlsx.xl.worksheets['sheet1.xml'];
$('row c[r^="C"]', sheet).attr('s', '0');
}
},
But note that will set cell type to GENERAL, not TEXT.
This is searching for all cells (row c) in third column (r^="C") and setting the style (s attribute) to 0 (the datatables built-in style for GENERAL content).
If you are reading this answer trying to do the opposite, formating numbers as numbers and dates as dates, the following code did the trick for me:
// (...)
buttons: [
{
extend: 'excelHtml5',
title: "Your Report Name",
exportOptions: {
columns: ':visible',
format: {
body: function (data, row, column, node) {
if (column === 3) { // if you have a number in 4th column
return parseFloat(data);
} else if (column === 2) { // if you have a date in 3rd column
var dateVal = Date.parse(data); // yyyy-MM-dd
var ticks = Math.round(25569 + (dateVal / (86400 * 1000)));
return ticks;
} else {
return data;
}
}
}
},
customize: function (xlsx, data) {
var sheet = xlsx.xl.worksheets['sheet1.xml'];
var styles = xlsx.xl['styles.xml'];
var dateStyle = "<xf numFmtId='14' fontId='0' fillId='0' borderId='0' applyFont='1' applyFill='1' applyBorder='1' xfId='0' applyNumberFormat='1' />";
styles.childNodes[0].childNodes[5].innerHTML += dateStyle;
$('row c[r^="D"][s=65]', sheet).attr('s', '64');
$('row c[r^="C"][s=65]', sheet).attr('s', '67');
}
},

datatables format values with text align

I am using jQuery data tables and fill the data via ajax as json:
https://datatables.net/examples/ajax/simple.html
var tbl = $('.mytbl').DataTable({
"ajax": {
url: "ajax/getData.php",
type: "POST"
}
});
The response of getData.php will be like this:
$myArray['data'][] = array(
"Value 1",
"Value 2",
"Value 3"
}
echo json_encode($myArray);
This works fine:
But how can I define that - for example - value 2 should be text-align right in my table?
Try this
var tbl = $('.mytbl').DataTable({
"ajax": {
url: "ajax/getData.php",
type: "POST"
},
'columnDefs': [{
"targets": 1,
"className": "text-right",
}]
});
You can use render method available in Datatables.
{
data: 'value 2 column',
render: function ( data, type, row ) {
return `<span style="text-align:right">${data}</span>`;
}
}
You can also use css if all column values are right aligned.

how can I read my id row from datatables jquery in php / codeigniter?

I want to get the row id to after sent it to php code,but im using datatables jquery plugin , however I show my id into datables , but datatables is generating td instead of inputs. if it were it will be easy to read it in php, but how can I read my row id of datable in php... I tried $_POST, but I cant because I havent any name on tds. other thing im using codeigniter. once I can read my id row I can use it for where id = id to update my item.
table
var table = $('#example').DataTable({
"lengthChange": false,
responsive: true,
dom: 'Blfrtip',
buttons: [{
extend: 'excelHtml5',
exportOptions:{
columns: [1,2,3,4,5,6]
}
},{
extend: 'csvHtml5',
exportOptions:{
columns: [1,2,3,4,5,6]
}
},{
extend: 'pdf',
exportOptions: {
columns: [1,2,3,4,5,6]
}
}],
ajax: {
url: URL_GET_DATATABLE,
type: 'POST',
},
columnDefs:[{
targets: -1,
data: null,
defaultContent: "<a href='#'><span class='glyphicon glyphicon-pencil'></span></a>"
},{
targets: 6,
render: function (data) {
return (data == 1) ? "<span class='label label-success'>active</span>":"<span class='label label-danger'>inactive</span>";
}
}],
fnRowCallback: function (data,nRow) {
if (nRow[6] == 0) {
$(data).css({'background-color':'#f2dede'});
}else if(nRow[6] == 1){
$(data).css({'background-color':'#dff0d8'});
}else{
}
}
});
model
public function datatable(){
$this->db->select('id,descripcion,precio_compra,precio_venta,precio_mayoreo,existencia_minima,existencia,storelte_articulos.status');
$this->db->from('storelte_articulos');
$query = $this->db->get();
return $query->result_array();
}
controller
public function datatable(){
$array = $this->products->datatable();
$this->json($array);
$data = array();
foreach ($array as $rows){
array_push($data, array(
$rows['id'],
$rows['descripcion'],
$rows['precio_compra'],
$rows['precio_venta'],
$rows['precio_mayoreo'],
$rows['existencia'],
$rows['status']
));
}
$this->json(array('data' => $data));
}
update controller
public function updateProduct($data){
$this->db->update('storelte_articulos',$data);
$this->db->where('id');
}
You need to put your ID into an input, but set it as hidden. That way the data isn't being shown to the end user, but it is available through post data.
As it is able to be seen with developer tools / inspect I would suggest encoding it for display then decoding it for use with the database queries.

JQuery DataTables - Catch 'ajax' response

I have an web-application that uses JQuery DataTables. It uses the ajax parameter for requesting and inserting JSON data into the table.
However, at the top of the requested .php file it is checked whether the user is logged in. If this check fails it echoes a JSON notice.
<?php
session_start();
if (!isset($_SESSION['logged']) || $_SESSION['logged'] !== true) {
$array = array(utf8_encode('logged')=>utf8_encode('false'));
echo json_encode($array);
exit;
}
?>
table = $('#active-issues').DataTable({
"scrollY": pixels,
"dom": '<"top"if>rt<"bottom"><"clear">',
"paging": false,
"responsive":true,
"bProcessing": true,
"ajax": {
"data": function(){
$('#active-issues').DataTable().ajax.url(
"php/get_issues.php"
+ "?id=" + id
+ "&customer_id=" + customerid
);
}
},
columns: [
{ responsivePriority: 1 },
{ responsivePriority: 2 },
{ responsivePriority: 4 },
{ responsivePriority: 3 },
{ responsivePriority: 5 },
{ responsivePriority: 6 },
{ responsivePriority: 7 }
],
"columnDefs": [
{ "type": "alt-string", targets: 5},
{ "type": "alt-string", targets: 6},
]
});
table.ajax.reload(null, false);
Is it possible to catch the response given to JQuery DataTables? So that I can check whether result is { logged: "false" } and act accordingly?
Took a while and the help of 'allan' from datatables forums. But the problem is finally solved.
via dataSrc it's possible to manipulate the ajax result before it is printed in the table, I, however, used it to check whether the result contains logged and whether it equals to false and act accordingly if it does:
"ajax": {
"data": function(){
$('#active-issues').DataTable().ajax.url(
"php/get_issues.php?id=" + id + "&customer_id=" + customerid
);
},
"dataSrc": function ( json ) {
if(typeof json['logged'] != "undefined") {
if (json['logged'] == 'false') {
location.replace('php/logout.php');
}
}
return json.aaData;
}
},
Yes, this can be done if you do your ajax cal externally i.e perform an independent ajax request to obtain the response and the identify if the response contains
{ logged: "false" } and the populate the data to the data table accordingly.

Categories