Datatables plugin for jQuery. How to hide rows? Export to Excel still showing hidden rows - datatables

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/

Related

How to reload dataTables from VueJS after adding or editing?

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.

How to put an html element in dojo dgrid table header

I want to place a hyperlink in the <th> of dojo dgrid table, but it is not possible when I tried it declarative
<thead>
<tr>
<th data-dgrid-column="{ field:'AVAILABLE_BALANCE',resizable:true}">Available
Balanceclick
</th>
</tr>
</thead>
it displays like
Available Balance click
How to do it
You can use the column renderHeaderCell do achieve this.
using HTML to grid way
<thead>
<tr>
<th data-dgrid-column="{ field:'AVAILABLE_BALANCE',resizable:true,
renderHeaderCell:customRenderHeaderCell}">
</th>
</tr>
</thead>
JavaScript:
function customRenderHeaderCell(node){
var div = document.createElement("div");
div.innerHTML = "Available Balance<a href='#'>click</a>";
return div;
}
using programmatic way
require([ 'dgrid/Grid' ], function (Grid) {
var columns = {
first: {
label: "First Name"
},
last: {
label: "Last Name"
},
balance: {
field: 'AVAILABLE_BALANCE',
resizable: true,
renderHeaderCell: function(node){
var div = document.createElement("div");
div.innerHTML = "Available Balance<a href='#'>click</a>";
return div;
}
}
};
var grid = new Grid({ columns: columns }, 'grid');
grid.renderArray(arrayOfData);
});

How to get data from all selected rows in datatable?

I have a simple table :
<div class="col-md-12 top-buffer">
<table id="table-data" class="table table-striped table-bordered">
<thead>
<tr>
<th></th>
<th>Code</th>
<th>Name</th>
<th>Postal Code</th>
<th>City</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
I implemented the selection of multiple rows using this :
var rows_data = [];
$(document).ready(function () {
$('#table-data tbody').on('click', 'input[type="checkbox"]', function(e) {
var $row = $(this).closest('tr');
if(this.checked){
$row.addClass('selected');
} else {
$row.removeClass('selected');
}
e.stopPropagation();
});
$('#table-data').on('click', 'tbody td, thead th:first-child', function(e) {
$(this).parent().find('input[type="checkbox"]').trigger('click');
});
}
What I'd like to do is add/remove the data of a row in rows_data[] when I select/deselect one.
How should I do to access the data (and also the index) of a row ?
Thanks !
Well I found something quite simple, here it is :
var rows_selected = [];
var table = $('#table-data').DataTable();
$(document).ready(function () {
$('#table-data tbody').on('click', 'input[type="checkbox"]', function(e) {
var $row = $(this).closest('tr');
var data = table.row($row).data();
var key = data[1];
if(this.checked){
$row.addClass('selected');
rows_selected[key] = data;
} else {
$row.removeClass('selected');
delete rows_selected[key];
}
e.stopPropagation();
});
}
Alternatively, you can clear and rebuild your rows_data array with a little less code:
var rows_data = [];
$(function() {
var table = $('#table-data').DataTable();
$('#table-data tbody').on('click', 'input[type="checkbox"]', function(e) {
var $row = $(this).closest('tr');
if (this.checked) {
$row.addClass('selected');
} else {
$row.removeClass('selected');
}
rows_data = [];
$('#table-data tr.selected').each(function() {
rows_data.push(table.row($(this)).data());
});
e.stopPropagation();
});
$('#table-data').on('click', 'tbody td, thead th:first-child', function(e) {
$(this).parent().find('input[type="checkbox"]').trigger('click');
});
});

How can we change width of search fields in DataTables

Can I change the width of search text fields in dataTables ?
I am writing following code right now but it is not working.
$('#example').dataTable()
.columnFilter({ sPlaceHolder: "head:before",
aoColumns: [ { type: "text",width:"10px" },
{ type: "date-range" },
{ type: "date-range" }
]
});
And if my dataTables is dynamically generated like as gven below:
$('#example').dataTable({
"aaData": aDataSet,
"aoColumns": [
{ "sTitle": "#","sWidth": "10px" },
{ "sTitle": "ID" },
{ "sTitle": "Staff Name" },
{ "sTitle": "Rig Days" },
{ "sTitle": "Manager"},
{ "sTitle": "Grade"},
{ "sTitle": "Tools"},
{ "sTitle": "Vacations"},
{ "sTitle": "Presently On"},
]
});
}
How to add Search field in this dynamically created DataTable to search by each column?
None of the above solution worked for me; then I got this:
$(document).ready(function () {
$('.dataTables_filter input[type="search"]').css(
{'width':'350px','display':'inline-block'}
);
});
And it worked perfectly!
If you want to place a placeholder too inside the search box use this ..
$('.dataTables_filter input[type="search"]').
attr('placeholder','Search in this blog ....').
css({'width':'350px','display':'inline-block'});
And this will work for sure.
To change the search box width, all I had to do was go into my .css file and enter the following:
.dataTables_filter input { width: 300px }
it's worked for me
<script>
var datatable = $('#table').DataTable({
...<datatables properties>,
initComplete: function () {
$('.dataTables_filter input[type="search"]').css({ 'width': '350px', 'display': 'inline-block' });
}
</script>
The only thing worked for me is this css.
$(document).ready(function(){
$('#datatable-buttons_filter').css({"position":"relative","left":"-100px"});
});
try to use css to change the width
example
.text_filter{
width:45%;
min-width:200px;
}
I applied this solution in my environment (Laravel 5.2, yajra/Laravel-DataTables 6.0, Bootstrap 3.x):
My table:
<table id="my-table" class="table table-striped table-hover" style="font-size: 80%">
<thead>
<tr>
<th class="input-filter" style="text-align:center;width: 5%">ID</th>
...
</tr>
</thead>
<tbody></tbody>
<tfoot>
<tr>
<th style="text-align:center;width: 5%">ID</th>
...
</tr>
</tfoot>
My script:
<script type="text/javascript">
var dt = $('#my-table').DataTable({
stateSave: true,
responsive: true,
processing: true,
serverSide: true,
order: [[ 0, "desc" ]],
lengthMenu: [[5, 10, -1], [5, 10, "All"]],
ajax: {
url: '...',
},
columns: [
{data: 'id', name: 'id',orderable:true,searchable:true},
...
],
language: {
url: '....'
},
initComplete: function () {
this.api().columns('.input-filter').every(function () {
var column = this;
var input = document.createElement("input");
// start - this is the code inserted by me
$(input).attr( 'style', 'text-align: center;width: 100%');
// end - this is the code inserted by me
$(input).appendTo($(column.footer()).empty())
.on('keyup', function () {
var val = $.fn.dataTable.util.escapeRegex($(this).val());
column.search(val ? val : '', true, true).draw();
});
});
}
});
</script>
here is the repeater
<asp:Repeater ID="rptClients" runat="server">
<HeaderTemplate>
<table id="example" class="display">
<thead>
<tr style="color:#fff;">
<th>Edit</th>
<th>Client Name</th>
<th>Address</th>
<th>City</th>
<th>State</th>
<th>Zip</th>
<th>Phone</th>
<th>Fax</th>
<th>Client Type</th>
<th>Active</th>
</tr>
<tr id="filterRow">
<td>Edit</td>
<td>Client Name</td>
<td>Address</td>
<td>City</td>
<td>State</td>
<td>Zip</td>
<td>Phone</td>
<td>Fax</td>
<td>Client Type</td>
<td>Active</td>
</tr>
</thead>
<tfoot style="display:none;">
<tr>
<td> </td>
</tr>
</tfoot>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><div class="padBtm-05 padTop-10"><asp:Button runat="server" ID="btnEdit" Text="Edit" /></div></td>
<td>
<%# Container.DataItem("ClientName")%>
</td>
<td>
<%# Container.DataItem("ClientAddress")%>
</td>
<td>
<%# Container.DataItem("ClientCity")%>
</td>
<td>
<%# Container.DataItem("State")%>
</td>
<td>
<%# Container.DataItem("ClientZip")%>
</td>
<td>
<%# Container.DataItem("ClientPhone")%>
</td>
<td>
<%# Container.DataItem("ClientFax")%>
</td>
<td>
<%# Container.DataItem("ClientType")%>
</td>
<td>
<%# Container.DataItem("Active")%>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
There are filters on all columns. Here I actually hide the edit column filter since it doesn't need one. If i don't render a filter for this column my filtering is off 1 column. In the javascript i target my table row which will end up being my title placeholder. Based on the placeholder name you can run an if statement that allows you to target the input element and set the width of the item. I have found setting the width of the filter sets the column width on the table.
// apply the input styling
$('#example thead td').each(function (i) {
var title = $('#example thead th').eq($(this).index()).text();
if (title == "Edit") {
var serach = '<input type="text" style="display:none;" placeholder="' + title + '" />';
} else if (title == "Client Name") {
var serach = '<input type="text" style="width:370px;" placeholder="' + title + '" />';
} else if (title == "Zip") {
var serach = '<input type="text" style="width:50px;" placeholder="' + title + '" />';
} else {
var serach = '<input type="text" placeholder="' + title + '" />';
}
$(this).html('');
$(serach).appendTo(this).keyup(function () { table.fnFilter($(this).val(), i) })
});
// Apply the search
table.columns().every(function () {
var that = this;
$('input', this.footer()).on('keyup change', function () {
if (that.search() !== this.value) {
that
.search(this.value)
.draw();
}
});
});
I have used the below code while using dataTables
JS
$('#du_ft_table').dataTable( { <br/>
"bProcessing": true,<br/>
"bServerSide": true,<br/>
scrollX: true,<br/>
"sAjaxSource": "../server_processing_man.php?sourceC=du_ft&rights=1&mandatory=1&retailer_id=2725",
"aoColumns": [
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
{ "mData": function(obj) {
return '<a class="btn btn-xs btn-primary" href="EBSNL_NW='+obj[0]+'" alt="Edit" title="Edit"><i class="fa fa-pencil-square-o"></i></a>';
}}
]
} );
$('.dataTables_scrollFootInner tfoot th').each( function () {<br/>
var title = $(this).text();<br/>
if(title != '') $(this).html( '<input type="text" placeholder="Search '+title+'" />' );<br/>
});
var duft_table = $('#du_ft_table').DataTable();
// Apply the search
duft_table.columns().every( function () {<br/>
var that = this;<br/>
$( 'input', this.footer() ).on( 'keyup change', function () {<br/>
if ( that.search() !== this.value ) {<br/>
that.search(this.value).draw();<br/>
}<br/>
} );
});
Nativ javascript solution.
$(document).ready(function() {
$('#yourTableId').DataTable();
var addressTableFilter = document.getElementById('addressTable_filter');
addressTableFilter.firstChild.getElementsByTagName('input')[0].style.width = "400px";
addressTableFilter.firstChild.getElementsByTagName('input')[0].setAttribute('placeholder', 'Search');
addressTableFilter.firstChild.removeChild(document.getElementById('addressTable_filter').firstChild.firstChild);
});
Dont forget to wrap everything inside document ready(if u using it)otherwise other lines may kick in before datatable is initiated and you will get error.
This will also remove search label and add it as placeholder inside input box.

DataTables : aoColumns doesn't show a toggle image column

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>";}}
],