I have a pretty simple datatables object. I bind it to an array of objects, specify the data fields and it works. The problem is when I try to implement the CSV export. It always only wants to export the first row of the table. Any ideas?
Here's where my code stands at the moment. And to be sure, I've made sure that the button and select libraries are included but that has made no difference.
<table id="tblData" style="display:none;">
<thead>
<tr id="trDataTableHeader">
<th data-s-type="string">Name</th>
<th data-s-type="string">Address</th>
<th data-s-type="string">Phone</th>
<th data-s-type="string">Website</th>
<th data-s-type="string">Types</th>
</tr>
</thead>
</table>
...
table = $('#tblData').DataTable({
dom: 'rtB',
data: tableData,
columns: [
{ "data": "name" },
{ "data": "address" },
{
"data": "phone_number",
defaultContent: ""
},
{
"data": "website",
defaultContent: ""
},
{
"data": "types",
defaultContent: ""
},
],
buttons: [{
extend: "csv",
text: "Export",
exportOptions: {
modifier: { search: "none", selected: false}
}
}],
select: false,
lengthChange: false,
sort: false,
paging: false
});
After a lot of digging, I made an accidental discovery when I removed the column data type specifications. I got an error message that str.replace is not a function.
Turns out that the parseInt and parseFloat base functions were being overridden by another developer on that page and was causing a problem but DataTables was too graceful to tell me.
This is why you don't override base javascript functions unless you absolutely have to.
Related
I am populating a table with datatables. The table has four columns always. But I need to add another column which can be shown or hidden based on boolean value.
My code so far:
{% show_extra_fields_button = show_extra_fields_bool %}
<table class="display" id="fields_datatable" class="fields_datatable">
<thead>
<tr>
<th>Name</th>
<th>Place</th>
<th>Email</th>
<th>Phone</th>
<th>Add Extra</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script src="/static/js/vendor/datatables.min.js"></script>
<script>
$(document).ready(function() {
$("#fields_datatable").dataTable({
ajax: {
"processing": true,
"dataSrc": "",
url: 'app/personFields/',
},
"columns": [
{ "data": "name" },
{ "data": "place" },
{ "data": "email" },
{ "data": "phone" },
]
})
if (show_extra_fields_button) {
$("#fields_datatable tr").each(function(){
$(this).append("<td><button>Add Extra</button</td>");
});
}
});
</script>
Here I would want to show the Add Extra column based on the boolean value. I want the header and the column values which will be buttons to be added using js.
How can I do that?
You can use data tables built-in functionality.
To add a button column you can use the following column definition:
{
"data": null,
"name": "buttonColumn",
"render": function (data, type, row) {
return '<button>Add Extra</button>';
}
}
Then use initComplete callback to set the columns' visibility once table has fully been initialised, data loaded and drawn:
$("#fields_datatable").dataTable({
ajax: {
type: "GET",
contentType: "application/json; charset=utf-8",
url: 'app/personFields/',
},
"columns": [
{ "data": "name" },
{ "data": "place" },
{ "data": "email" },
{ "data": "phone" },
{
"data": null,
"name": "buttonColumn",
"render": function (data, type, row) {
return '<button>Add Extra</button>';
}
}
],
"initComplete": function (settings, json) {
// get instance of datatable
table = settings.oInstance.api();
// get column using its name and set visibility
table.column('buttonColumn:name').visible(show_extra_fields_button);
}
});
You can put - instead of deleting that <td> for example <td>-</td>
You can add to the table header just the same way you are adding to the table body.
if (show_extra_fields_button) {
$('#fields_datatable thead tr').append('<th>Add Extra</th>')
}
Execute it just one time.
I have tried and searching lot of solution but not solve my problem, even at dataTables website. The problem is how to display nested array in json using DataTables? Fo example below, How if I just want to display l3_id: "1" data only.
I try to understand this link but not really understand. Example
There is no error at console and network tab.
DataTable not appear, including dataTables features such as search box, pagination. (The CDN/library has been imported)
JSON
{
"data": [
{
"project_id": "1",
"l1_task": [
{
"l1_id": "1",
"l2_task": [
{
"l2_id": "1",
"l3_task": [
{
"l3_id": "1",
"l3_name": "My name"
}
]
}
]
}
]
}
]
}
JS (I am applying HTML in JS)
"<table id='Layer3Table' class='table dt-responsive nowrap' style='width:100%'>"+
"<thead>"+
"<tr>"+
"<th class='text-center'>ID</th>"+
"<th class='text-center'>Activity Name</th>"+
"</tr>"+
"</thead>"+
"</table>"+
$('#Layer3Table').DataTable({
ajax: {
url: url_project_detail",
dataSrc : "data"
},
columns: [
{ data : "l1_task.0.l2_task.0.l3_task.0.l3_id" },
{ data : "l1_task.0.l2_task.0.l3_task.0.l3_name" },
],
});
Either define your table, including all tbody content in HTML, then use DataTables to enable the search etc features. If you do it this way you don't need to set the url or columns (although you can still set other options).
$('#Layer3Table').DataTable();
Or if you want to make use of the url and column features, create the basic table structure in HTML
<table id='Layer3Table' class='table dt-responsive nowrap' style='width:100%'>
<thead>
<tr>
<th class='text-center'>Project ID</th>
<th class='text-center'>Project Name</th>
<th class='text-center'>Project Description</th>
<th class='text-center'>Project Status</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Then set up your DataTable separately in JavaScript.
$('#Layer3Table').DataTable( {
ajax: {
url: url_project_detail,
crossDomain : true,
type : "POST",
cache : false,
dataType : "json",
contentType: "application/json",
dataSrc : "data",
},
columns: [
{ data : "l3_id", "className": "text-center" },
{ data : "l3_name", "className": "text-center" },
{ data : "l3_description", "className": "text-center" },
{ data : "l3_status", "className": "text-center" }
],
});
What you appear to be doing is looping over your results and creating a DataTable for each of them, which is why it doesn't understand.
I want to show my record data into table enhanced by jQuery DataTables plugin using server-side processing mode. I followed the docs Datatables Server side but in my table I can't show the record data.
Here's my Ajax response:
{
"draw": 0,
"recordsTotal": 4,
"recordsFiltered": 4,
"data": [
[
27,
"Brokoli Segar",
"25000"
],
[
28,
"Tomat Super",
"2000"
],
[
29,
"Oreo Roll",
"9400"
],
[
30,
"Close Up Toothpaste Fire Freeze",
"7000"
]
],
"queries": [
{
"query": "select count(*) as aggregate from (select '1' as row_count from `product` where `product`.`deleted_at` is null) count_row_table",
"bindings": [],
"time": 0.79
},
{
"query": "select `id`, `name`, `price` from `product` where `product`.`deleted_at` is null",
"bindings": [],
"time": 0.68
}
],
"input": []
}
My HTML table:
<table class="table table-bordered" id="tabelStokBarang">
<thead>
<tr>
<th>ID</th>
<th>Nama Barang</th>
<th>Harga Barang</th>
</tr>
</thead>
</table>
My JavaScript:
$('#tabelStokBarang').DataTable({
processing: true,
serverSide: true,
ajax: '{!! route('admin.product.stock.getAll') !!}',
columns: [
{ data: 'id', name: 'id' },
{ data: 'name', name: 'name' },
{ data: 'price', name: 'price' }
]
});
My result in table is still "No data available". I don't know what I've missed.
Remove columns to match your data because you're returning rows as arrays but with columns property expecting rows to be objects with properties id, name and price. See the code below:
$('#tabelStokBarang').DataTable({
processing: true,
serverSide: true,
ajax: '{!! route('admin.product.stock.getAll') !!}'
});
Another potential problem is that your draw parameter is 0. Your script should return draw parameter with the same value of the draw parameter in the request. I believe it starts at 1 and then increments with every request.
From the manual:
draw
The draw counter that this object is a response to - from the draw parameter sent as part of the data request. Note that it is strongly recommended for security reasons that you cast this parameter to an integer, rather than simply echoing back to the client what it sent in the draw parameter, in order to prevent Cross Site Scripting (XSS) attacks.
This is linked to the question here. However, my case is a bit different. I would like to implement the same datatables example from the other question which is here. As you can see you have to pass the column names to be able to initialize the table headers like below
"columns": [
{ "data": "name" },
{ "data": "position" },
{ "data": "office" },
{ "data": "extn" },
{ "data": "start_date" },
{ "data": "salary" }
]
The problem is that I would not know the header names beforehand as they will change. I've tried initializing the column names when I get the data from ajax like below using a 3rd variable (see where it says 'pay attention to this line' but this doesn't work.
//PAY ATTENTION TO THIS LINE
var columnsHeaders = [];
var ab = $('#dynamicScenarioTable').DataTable({
"bDestroy": true,
"dom": 'T<"clear">lfrtip',
"ajax": {
"type": "POST",
"url": "dynamicScenario.htm",
"data": tags,
"dataType": "json",
"dataSrc": function(json){
//PAY ATTENTION TO THIS LINE
columnsHeaders.push({"data": json.header });
return json.vals;
},
"error": function(exception)
{
displayMessageOnError();
}
},
//PAY ATTENTION TO THIS LINE
"columns": [columnsHeaders],
tableTools: tableDefaultS.tableTools
});
Any ideas?
You can add a data-source attribute to the TH tags that are built on your table header. You can then have jQuery read those and construct the array to send into the DataTable constructor.
<tr>
<th data-source="name">Name</th>
<th data-source="position">Postion</th>
<th data-source="start_date">Start Date</th>
</tr>
Then in your JavaScript do something like this to construct the array
var columnsHeaders = [];
$("#dynamicScenarioTable thead th").each(function() {
colmnsHeaders.push(
{
data : $(this).data("source")
}
);
});
// construct your DataTable after this
i'm currently using Datatables for a Custom system and i would like to disable Sort for every column but the first one.
I tried with the following code wich is working fine when i add values separated by comma
"aoColumnDefs": [
{ 'bSortable': false, 'aTargets': [ 1, 2, 3, 4 ] }
],
But my tables column number vary for each individual file so i can have 3 or maybe 12 columns, and i don't want to have to manually add the values for each file.
If i add more values than the columns i have in one file i get the following error, and an execution stop
Uncaught TypeError: Cannot read property 'className' of undefined
So, is there any way i can get those index and pass them to the function?
Thanks!
You can add a specific class to the TH element that you do not want to be sortable.
<table>
<thead>
<th>
...
</th>
<th class="no-sort">
...
</th>
</thead>
<tbody>
...
</tbody>
</table>
And then you can specify this class in your aTargets parameter.
"aoColumnDefs": [
{ 'bSortable': false, 'aTargets': ['no-sort'] }
]
View here for more information on the Column specific options.
And then you can specify this class in your aTargets parameter.
columnDefs: [ { orderable: false, targets: [1,2,3,4,5,6,7,8,9] } ]
This worked for me and seems more practical (though not exactly elegant)
columnDefs: [
{
"targets": [0],
"orderable": true
}, {
"targets": [''],
"orderable": false
}
]