I've been struggling with this code. I need to avoid specific columns from being exported. I have done that but I don't know how to export the text inside any input element.
Here is the code:
$("#campaignMaterialsTable table").DataTable({
dom: 'Bfrtip',
buttons: [
{
extend: 'excel',
className: 'export-button',
text: 'Export as Excel',
columns: ':not(.notexport)',
//exportOptions: {
// format: {
// body: function (data, row, column, node) {
// //
// //check if type is input using jquery
// return $(data).is("input") ?
// $(data).val() :
// data;
// },
// columns: ':not(.notexport)'
// }
//},
title: 'Campaign Materials'
}]
});
I don't know here to put the code at the right place.. while initializing..
I referred to this links, but still not getting what I want:
https://datatables.net/forums/discussion/50724/export-values-typed-in-input-box-excelhtml5
https://datatables.net/forums/discussion/42205/export-data-with-text-box-in-td-of-data-table#latest
https://datatables.net/extensions/buttons/examples/html5/outputFormat-function.html
https://datatables.net/forums/discussion/50724/export-values-typed-in-input-box-excelhtml5
I assume you have a DataTable containing one or more input fields, something like this:
The user can type values into the input fields.
You want to export data to Excel, so that the result looks like this:
Here we can see the user-provided data as well as the standard table data.
To achieve this, I used the following table data:
<table id="example" class="display nowrap dataTable cell-border" style="width:100%">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>Adélaïde Nixon</td>
<td>System Architect</td>
<td><input type="text" id="office" name="office"></td>
<td>432434</td>
<td>2011/04/25</td>
<td>$320,800</td>
</tr>
<tr>
<td>John Smith</td>
<td>Maager</td>
<td><input type="text" id="office" name="office"></td>
<td>6123</td>
<td>2011/04/25</td>
<td>$320,800</td>
</tr>
<tr>
<td>John Smith 2</td>
<td>Director</td>
<td><input type="text" id="office" name="office"></td>
<td>6123</td>
<td>2011/04/25</td>
<td>$320,800</td>
</tr>
</tbody>
</table>
And I used the following DataTable initialization code:
<script type="text/javascript">
$(document).ready(function() {
$('#example').DataTable({
dom: 'Bfrtip',
buttons: [
{
extend: 'excel',
exportOptions: {
format: {
body: function ( inner, rowidx, colidx, node ) {
if ($(node).children("input").length > 0) {
return $(node).children("input").first().val();
} else {
return inner;
}
}
}
}
}
]
});
});
</script>
The body function assumes that, for input fields, there is only an input field in the cell (i.e. the input field is not contained in a form or any other element).
It uses the node parameter to check for input data, to avoid data formatting issues that could occur (e.g. with dates). I recommend doing that rather than using $(data).is("input").
If there is no input field found in the cell, then the cell contents (inner) are returned.
If the structure of your table does not match these assumptions, then you may need to adjust the above code, of course.
Edit
Regarding the follow-up question about choosing which columns to export, there are various ways.
You can hard-code the column indexes you want to export (where index 0 means the first column). For example:
exportOptions: {
columns: [ 0, 1, 2, 3, 5 ],
format: {
body: function ( inner, rowidx, colidx, node ) {
if ($(node).children("input").length > 0) {
return $(node).children("input").first().val();
} else {
return inner;
}
}
}
}
This exports all columns apart from the Start Date column (index 4).
Or you can use the approach in your question, based on a class, I believe. I have not actually tried that one.
Take note of where the columns: [ 0, 1, 2, 3, 5 ] directive is placed - it is inside the exportOptions section.
you can use
exportOptions:{
columns: ':visible'
}
in below buttons
buttons: [
{
extend: 'pdf',
footer: true,
exportOptions: {
columns: ':visible'
}
},
it will export only visible columns
Related
I have a table:
<table class="table table-bordered table-hover" id="user-table">
<thead>
<tr>
<th data-field="id">Id</th>
<th data-field="name">Name</th>
<th data-field="email">Email</th>
<th data-field="company">Company</th>
<th data-field="actions">Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>John Doe</td>
<td>john#doe.com</td>
<td>Doe Inc.</td>
<td>
<div class="btn-group">
<i class="fa fa-pencil"></i>
</div>
</td>
</tr>
</tbody>
</table>
My current way to add row:
var columns = $.map(data,function(v,k){
return v;
});
var rowNode = table.row.add(columns).order([0, 'desc']).draw(false).node();
$(rowNode).addClass('selected');
setTimeout(function(){$(rowNode).removeClass('selected');}, 2000);
My data looks like this:
{
"data":[ {
"id": 2,
"name": "Jane Doe",
"email": "jane#doe.com",
"company": "Doe Inc."
}
]
}
Is there a way to add row based on columns? Instead of returning v on a mapped data, I can directly insert data[0] using row.add(). I've been searching but can't get the exact scenario.
Apparently, the purpose is for shuffled data. In a table that have 15 columns, I don't have to worry about the proper column arrangements.
I found this https://datatables.net/reference/api/row.add() example #1 but obviously the documentation says:
Data to use for the new row. This may be an array, object, Javascript object instance or a tr element. If a data structure is used (i.e. array or object) it must be in the same format as the other data in the table (i.e. if your table uses objects, pass in an object with the same properties here!).
If you specify columns (or columnDefs) with data attributes, you can add row or rows in JSON / object literal format:
columns: [
{ data: 'id' },
{ data: 'name' },
{ data: 'email' },
{ data: 'company' }
]
You must also specify the last column, even it is not targeting any data. You can use render(), createdCell() or defaultContent:
const actions = `
<div class="btn-group">
<i class="fa fa-pencil"></i>
</div>
`;
var table = $('#user-table').DataTable({
columns: [
{ data: 'id' },
{ data: 'name' },
{ data: 'email' },
{ data: 'company' },
{ data: null, defaultContent: actions }
]
...
})
Now you can insert data from above:
var rowNode = table.row.add(data.data[0]).order([0, 'desc']).draw(false).node();
or all rows :
table.rows.add(data.data).draw()
I'd like to know how I can use this same approach when loading data from database through an api. In the first time the dataTables loads fine. However, when I add a new record, then I need to load my dataTables again with the new record. Here's my html code:
<table class="table table-striped table-bordered table-hover" id="dataTables-eventos">
<thead>
<tr class="tbheader">
<th class="text-center">#</th>
<th>Nome do Evento</th>
<th class="text-center">Editar</th>
<th class="text-center">Deletar</th>
</tr>
</thead>
<tbody>
<tr v-for="ev in eventos" :key="ev.id" track-by="id">
<td class="text-center">{{ ev.id }}</td>
<td>{{ ev.name }}</td>
<td class="text-center"><a class="cursorpointer" v-on:click="showMessage()"><span class="glyphicon glyphicon-edit"></span></a></td>
<td class="text-center"><span class="glyphicon glyphicon-trash"></span></td>
</tr>
</tbody>
</table>
And here's my VueJS code:
mounted() {
this.getEventos();
},
methods: {
getEventos() {
axios.get('/api/eventos')
.then((response) => {
this.eventos = response.data})
.then((response) => {
$('#dataTables-eventos').DataTable({
responsive: true,
"aaSorting": [[ 1, "asc" ]],
"aoColumnDefs": [
{ "bSortable" : false, "aTargets": [0,2,3] },
{ "searchable": false, "aTargets": [2,3] }
],
language: {
url: '/js/dataTables/localization/pt_BR.json'
}
});
});
},
addNewRecord() {
axios.post('/api/eventos', { nomeEvento: this.nomeEvento });
}
So after adding (or editing) a new record on my DB how can I reload my dataTables so I can see the changes?
I just ran into a situation where I needed to use vue.js with datatables.net and had to use customized table html. I created a component that allowed me to format the table as I needed using template/v-for and refresh the datatable while preserving datatables.net functionality. I hope this helps someone down the road...
export default {
data() {
return {
dataTable: null
}
},
props: {
data: Array
},
watch: {
data() {
if (this.dataTable) {
this.dataTable.destroy();
}
this.$nextTick(() => {
this.dataTable = $("#table").DataTable({
language: {
emptyTable: "No Results Found"
}
});
});
}
}
}
You can do it without reloading all the data.
Just add this.nomeEvento to array eventos after posting to server.
I was able to figure out how to hide the rows I wanted using JQuery. I have a modal that pops out for the user deselects the checkbox on what rows they want to hide. It works perfectly but when I export it to excel it still displays the hidden rows. I am not using the API at all and I think that's my problem. I am hiding the rows by using .show() and .hide(). I am using the API to hide the columns and when I click my export to excel button it works just fine. Could anyone help me figure out how to hide rows and be able to export it to excel with the rows not showing on the spreadsheet?
HTML
<script type="text/javascript" language="javascript" src="https://cdn.datatables.net/buttons/1.2.4/js/dataTables.buttons.min.js">
</script>
<script type="text/javascript" language="javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jszip/2.5.0/jszip.min.js">
</script>
<script type="text/javascript" language="javascript" src="https://cdn.datatables.net/buttons/1.2.4/js/buttons.html5.min.js">
</script>
<table cellpadding="0" cellspacing="0" border="0" class="dataTable" class="example">
<thead>
<tr>
<th>Item</th>
<th>Store 1</th>
<th>Store 2</th>
<th>Store 3</th>
<th>Store 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sugar</td>
<td>21</td>
<td>95</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>Coffee</td>
<td>5</td>
<td>41</td>
<td>5</td>
<td>1</td>
</tr>
<tr>
<td>Banana</td>
<td>123</td>
<td>323</td>
<td>22</td>
<td>233</td>
</tr>
<tr>
<td>Gum</td>
<td>13</td>
<td>213</td>
<td>2</td>
<td>33</td>
</tr>
<tr>
<td>Milk</td>
<td>23</td>
<td>24</td>
<td>44</td>
<td>242</td>
</tr>
</tbody>
</table>
</div>
</body>
JavaScript
var table = $('.example').DataTable({
dom: 'Bfrtip',
buttons: [
{
extend: 'excelHtml5',
exportOptions: {
columns: ':visible'
},
text: 'Export to Excel'
},
],
});
// I get the attribute name from the checkbox and I match it with the id on the row and when the checkbox is unchecked I hide the rows.
$('input.rowsHideSeek').click(function() {
var name = $(this).attr('name');
if ($(this).is(':checked')) {
$('#' + name).show()
} else {
$('#' + name).hide()
}
});
This is what I came up with and it seems to work. It shows and hides rows and, on export, only shows rows not hidden.
here is it is on jsbin http://jsbin.com/qituvu/edit?output
The key part is that it uses the customizeData in the extended excelHtml5.
$(document).ready(function () {
// this just creates a critera to filter on
var faketype = 1;
for (var i = 0; i < dataStore.data1.length; ++i) {
dataStore.data1[i].type = faketype++;
if (faketype == 5) faketype = 1;
}
var aTable = $('#example').DataTable({
"data": dataStore.data1,
paging:false,
"columns": [
{ "data": "name" },
{ "data": "position" },
{ "data": "office", className: "editColumn" },
{ "data": "extn" },
{ "data": "start_date" },
{ "data": "salary" },
{ "data": "type"}
], dom: 'Bfrti',
"createdRow": function( row, data, dataIndex ) {
$(row).addClass('type_' + data.type);
},
buttons: [{text:"Excel",
extend: 'excelHtml5', customizeData: function (exData) {
var rowNodes = aTable.rows().nodes();
var newData = []
for (var i = (exData.body.length - 1) ; i >= 0; i--) {
if ($(rowNodes[i]).css("display") == "none") {
continue;
}
newData[newData.length] = exData.body[i];
}
// the loop reverses order so put it back
exData.body = newData.reverse();
}}]
});
// event handler for hiding and showing rows
$("input[name='hideType']").on("click", function () {
var c = $(this).val();
var isChecked = $(this).prop('checked');
$(aTable.rows('.type_' + c).nodes()).toggle(isChecked);
aTable.rows().invalidate().draw();
});
});
The problem with jQuery hide() / show() is that you will need to tweak any part of dataTables you are using, if you want to fake persistent "hidden" rows.
Here is a few plug-in methods that provide real hide() and restore() on rows in dataTables :
$.fn.dataTableExt.hiddenRows = {};
$.fn.dataTable.Api.register( 'row.hide()', function(selector) {
var row = this.row(selector);
if (row.length == 0) return -1;
var index = row.node()._DT_RowIndex;
$.fn.dataTableExt.hiddenRows[index] = row.node().outerHTML;
row.remove().draw(false);
return index;
});
$.fn.dataTable.Api.register( 'row.restore()', function(index) {
var row = $.fn.dataTableExt.hiddenRows[index];
if (row) {
this.row.add( $(row) ).draw(false);
delete $.fn.dataTableExt.hiddenRows[index];
return true;
}
return false;
});
Now you have table.row.hide() and table.row.restore(). The methods use the dataTables API, and does nothing but maintaining a list of removed rows by their unique indexes. A demo could look like this :
var table = $('#example').DataTable({}) ;
$('#example').on('click', 'tbody tr', function() {
var index = table.row.hide(this);
var $button = $('<button></button>')
.addClass('restore')
.attr('index', index)
.text('show #'+index);
$('body').prepend($button);
})
$('body').on('click', '.restore', function() {
var index = $(this).attr('index');
table.row.restore(index);
$(this).remove();
})
When you click on a row it is hidden (i.e removed); a restore button is generated for each hidden row. If you click on the button the corresponding row is restored.
Demo -> http://jsfiddle.net/s183ek2q/
I am using mRender to add checkboxes in the first column of the tbody... the correct css styling is being applied, but they are not stylized when I view the table. I can only assume this is because I am using mRender to add these values in, however, if I do other css like changing color of text it works fine. I have no problem with the checkbox in the thead being properly styled, but this is included by default with the html. Ideas?
the html:
<table class="table table-striped table-bordered table-hover" id="sample_1">
<thead>
<tr>
<th><input type="checkbox" class="group-checkable" data-set="#sample_1 .checkboxes" /></th>
<th>Username</th>
<th>Password</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr class="odd gradeX">
<td>Data 1</td>
<td>Data 2</td>
<td>Data 3</td>
<td>Data 4</td>
</tr>
</tbody>
</table>
the js:
$('#sample_1').dataTable({
//start my code
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "/assets/data-tables/test-normal.php",
//end my code
"aLengthMenu": [
[5, 15, 20, -1],
[5, 15, 20, "All"] // change per page values here
],
"aoColumnDefs": [ {
"aTargets": [ 0 ],
"bSortable": false,
"mRender": function ( data, type, full ) {
return '<input type="checkbox" class="checkboxes" value="'+data+'" />';
}
} ],
// set the initial value
"iDisplayLength": 5,
"sPaginationType": "bootstrap",
"oLanguage": {
"sLengthMenu": "_MENU_ records",
"oPaginate": {
"sPrevious": "Prev",
"sNext": "Next"
}
},
});
Had to use :
"fnInitComplete": function() {
$(".checkboxes").uniform();
}
You missed the mData portion
In aoColumns, not aoColumnDefs, use the following
{ "mData": null , // can use null, the numeric array number, or assoc array string
"mRender" : function ( data, type, full ) {
return '<input type="checkbox" class="checkboxes" value="'+data+'" />'}
},
I'm using DataTables as a data grid manager on my app. Everything works fine but until I'm equipped a hidden row info plugin. I tried many ways to change things but the first column of toggle image never showed up. Here's my code:
Javascript
var oTable;
/* Formating function for row details */
function fnFormatDetails(nTr){
var aData=oTable.fnGetData(nTr);
var sOut='<table cellpadding="7" cellspacing="0" border="0" style="border:solid 1px red;padding-left:50px;">';
sOut+='<tr><td>Renderingengine:</td><td>'+aData[2]+''+aData[3]+'</td></tr>';
sOut+='<tr><td>Linktosource:</td><td>Couldprovidealinkhere</td></tr>';
sOut+='<tr><td>Extrainfo:</td><td>Andanyfurtherdetailshere(imagesetc)</td></tr>';
sOut+='</table>';
return sOut;
}
$(document).ready(function() {
oTable=$('#labour_show').dataTable({
"fnDrawCallback": function(){//row highlighter
$('table#labour_show td').bind('mouseenter', function () { $(this).parent().children().each(function(){$(this).addClass('datatablerowhighlight');}); });
$('table#labour_show td').bind('mouseleave', function () { $(this).parent().children().each(function(){$(this).removeClass('datatablerowhighlight');}); });
},
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "inc/_labour_show_ajax.php",
"aoColumns":[null,null,null,{"fnRender": function(oObj){return "<a href='main.php?do=labour&action=edit&sid=" + oObj.aData[7] + "'>Edit</a>";} }],"aaSorting": [[1, 'asc']]
});
$('#labour_show tbody td img').live('click',function(){
var nTr = this.parentNode.parentNode;
if(this.src.match('details_close')){
/* This row is already open - close it */
this.src = "images/ico_expand.png";
oTable.fnClose( nTr );
}else{
/* Open this row */
this.src = "images/ico_collapse.png";
oTable.fnOpen( nTr, fnFormatDetails(nTr), 'details' );
}
});
});
_labour_show_ajax.php
This is an arrays from a server-side script
$aColumns = array('labr_uid', 'labr_fname', 'emplyr_comp','labr_sid');
HTML Code:
<table cellpadding="0" cellspacing="0" border="0" class="display" id="labour_show">
<thead>
<tr>
<th></th>
<th>Passport</th>
<th>Name</th>
<th width="30%">Employer</th>
<th>Edit</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="5" class="dataTables_empty"><img src="images/loading.gif" /></td>
</tr>
</tbody>
Screen Shot
No matter I've tried. The first column never shown up. Please suggest.
I count 5 columns in your html table, and 4 in your aoColumns
Either add another null
"aoColumns":[
null,
null,
null,
null,
{"fnRender": function(oObj){return "<a href='main.php?do=labour&action=edit&sid=" + oObj.aData[7] + "'>Edit</a>";} }],
or do mData and add this
{ "mData": null ,
"mRender" : function ( data, type, full ) {
return '<img src="images/ico_open.png" />';}
},
Matter of fact, i believe mRender is the choice now over fnRender, and you could replace your fnRender as well like this
{ "mData": null , // or aAData[4] or aaData['labor_sid']
"mRender" : function ( data, type, full ) {
return 'Edit';}
},
Heres a link to another SO i answered about it Adding a link to datatables for more information
try this one,, i think your missing the { "sClass": "" } on the others
"aoColumns": [
{ "sClass": "", "bSortable": false },
null,
null,
null,
{ "sClass": "" },
{ "sClass": "" },
{"fnRender": function(oObj){return "<a href='main.php?do=labour&action=edit&sid=" + oObj.aData[7] + "'>Edit</a>";}}
],