Referring to the Individual column searching (text inputs) and Individual column searching (select inputs) to use multiple filters on jQuery DataTable, I mixed them up in order to allow text inputs searches on some columns and select inputs searching on others.
It almost works, but select inputs don't work correctly: the first select input on the third column shows values of the first column, the second select input shows the second column, and so on.
$( document ).ready(function() {
$('#wbe_table tfoot th.search_th').each( function () {
var title = $(this).text();
$(this).html( '<input type="text" placeholder="Search '+title+'" />' );
} );
var oTable = $('#wbe_table').DataTable( {
orderCellsTop: true,
fixedHeader: true,
responsive: true,
lengthChange: true,
autoWidth: true,
pageLength: 50,
order: [[7, "desc"]],
columnDefs: [
{
targets: [4],
orderable: false
},
{
type: "currency",
targets: [7,8,9,10]
},
],
dom: 'Bfrtip',
buttons: [
'copy', 'csv', 'excel', 'pdf', 'print'
] ,
//Select input search
initComplete: function () {
var api = this.api();
$('.filterhead', api.table().footer()).each( function (i) {
var column = api.column(i);
var select = $('<select><option value=""></option></select>')
.appendTo( $(this).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>' );
} );
} );
}
});
// Text input search
oTable.columns().every( function () {
var that = this;
$( 'input', this.footer() ).on( 'keyup change', function () {
if ( that.search() !== this.value ) {
that
.search( this.value )
.draw();
}
} );
} );
});
Related
I'm using jquery and used datatable library.
I created my datatable like this:
$datatable = $('#datatable-buttons').DataTable({
keys: true, searching: false, "paging": false, "info": false,
buttons: [
{
extend: 'copyHtml5',
text: '<i class="fa fa-files-o"></i>',
titleAttr: 'Copy'
},
{
extend: 'excelHtml5',
text: '<i class="fa fa-file-excel-o"></i>',
titleAttr: 'Excel'
},
{
extend: 'csvHtml5',
text: '<i class="fa fa-file-text-o"></i>',
titleAttr: 'CSV'
}
],
orderCellsTop: true,
fixedHeader: true,
initComplete: function () {
var api = this.api();
// For each column
api
.columns()
.eq(0)
.each(function (colIdx) {
// Set the header cell to contain the input element
var cell = $('.filters th').eq(
$(api.column(colIdx).header()).index()
);
var title = $(cell).text();
$(cell).html('<input type="text" placeholder="' + title + '" />');
// On every keypress in this input
$(
'input',
$('.filters th').eq($(api.column(colIdx).header()).index())
)
.off('keyup change')
.on('keyup change', function (e) {
e.stopPropagation();
// Get the search value
$(this).attr('title', $(this).val());
var regexr = '({search})'; //$(this).parents('th').find('select').val();
var cursorPosition = this.selectionStart;
// Search the column for that value
api
.column(colIdx)
.search(
this.value != ''
? regexr.replace('{search}', '(((' + this.value + ')))')
: '',
this.value != '',
this.value == ''
)
.draw();
$(this)
.focus()[0]
.setSelectionRange(cursorPosition, cursorPosition);
});
});
}
});
I have a submit button to get data from my server and draw data to datatable:
function refreshDataTable(result) {
rowDataTable = PER_PAG * (CURRENT_PAGE - 1)
var rows = []
result.forEach((item => {
++rowDataTable
var data = [rowDataTable, item.order_id, "item.shipping.mobile", item.shipping.first_name, item.shipping.last_name, item.shipping.state, item.shipping.city, item.shipping.address, item.shipping.title, item.shipping.cost, item.shipping.delivery_time]
console.log("data",data)
rows.push(data)
}))
$datatable.rows.add(rows).draw();
}
it shows some inputs above each columns. but when I typing some texts it doesn't to filter my rows.
<script>
$(document).ready(function() {
$('#sortable').DataTable( {
initComplete: function () {
this.api().columns([0,1,2,3]).every( function () {
var column = this;
var select = $('<select><option value=""></option></select>')
// var select = $('<select><option value="">' + $(this.header()).html() + '</option></select>')
.appendTo( $(column.header()).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>' )
select.append( '<option>'+d+'</option>' )
} );
} );
}
} );
} );
$(document).ready(function() {
$('#sortable').DataTable({
"order": [[1, "asc"],[0, "asc"]],
"columns": [
null,
null,
null,
{"orderable": false},
{"orderable": false},
{"orderable": false},
],
"searching": true,
"paging": false,
"ordering": true,
"info": false
});
} );
</script>
These 2 separate blocks work well individually if the other is commented out, but I don't know how I can combine them to be one block so I can achieve default sorting and drop-down filters.
The aim is to have drop-down filters on columns [0,1,2,3], default sorting and have defaults number of rows shown = 50.
//like so:
<script>
$(document).ready(function() {
$('#sortable').DataTable( {
sort by default;
set default rows shown to 50;
put filter on first 4 colmuns;
})
})
</script>
Thanks in advance for your help.
Your "two blocks" are two initializations of a DataTables object made from the same table, which is why they don't work together. The good news is that you can just combine the two into a single block and they should work together, since none of the options you're using conflict with each other (as far as I can tell). It should look like this:
<script>
$(document).ready(function() {
$('#sortable').DataTable( {
pageLength: 50, //This is the option which will give you 50 rows by default
order: [[1, "asc"],[0, "asc"]],
columns: [
null,
null,
null,
{"orderable": false},
{"orderable": false},
{"orderable": false},
],
searching: true,
paging: false,
ordering: true,
info: false,
initComplete: function () {
this.api().columns([0,1,2,3]).every( function () {
var column = this;
var select = $('<select><option value=""></option></select>')
// var select = $('<select><option value="">' + $(this.header()).html() + '</option></select>')
.appendTo( $(column.header()).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>' )
select.append( '<option>'+d+'</option>' )
} );
} );
}
} );
} );
</script>
You'll note that all I did was put the options selected in the second block into the first block and add the pageLength option to start the number of rows at 50. You can optionally surround the names of the options with "" if you want, but it's unneccessary, just a preference thing (e.g. "order" vs order).
You should only ever have one DataTables initialization .DataTable() call in your code per page.
I currently have a DataTable that has data download buttons in format that I'm looking for:
$(document).ready(function() {
$('#dataTables-example').DataTable( {
dom: 'Bfrtip',
buttons: [
'copyHtml5',
'excelHtml5',
'csvHtml5',
'pdfHtml5'
]
} );
} );
However, I want to be able to filter columns with a dropdown menu in the footer - exactly like in the example in this link:
https://datatables.net/examples/api/multi_filter_select.html
The initialization code for that is:
$(document).ready(function() {
$('#dataTables-example').DataTable( {
initComplete: function () {
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>' )
} );
} );
}
} );
} );
What I want is to combine these two functionalities - column filter and data download options. I've tried moving around the button and dom snippet into the code above:
dom: 'Bfrtip',
buttons: [
'copyHtml5',
'excelHtml5',
'csvHtml5',
'pdfHtml5'
]
} );
But I've had no luck getting it to display correctly (or at all).
I had an engineering breakthrough and did the obvious thing, added the DOM settings before:
initComplete: function(){.......
And it worked.
Complete function:
$(document).ready(function() {
$('#dataTables-example').DataTable( {
dom: 'lBfrtip',
buttons: [
'copyHtml5',
'excelHtml5',
'csvHtml5',
'pdfHtml5'
],
initComplete: function () {
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>' )
} );
} );
}
});
});
I have a current jQuery DataTable in place that is functioning properly:
var $dataTable = $('#example1').DataTable({
"ajax": 'api/tableSearch.php',
"iDisplayLength": 25,
"order": [[ 6, "desc" ]],
"scrollY": 600,
"scrollX": true,
"bDestroy": true,
"columnDefs": [{
"targets": 0,
"render": function (data, type, full, meta){
return '<a class="editLink" href="#">Edit</a><a class="deleteLink" href="#">Del</a>':
}
}]
});
As stated, the above code works accordingly...the search filter works, the sorting works, everything works.
What I would like to do is add a column search to this datatable, as shown here:
https://www.datatables.net/release-datatables/examples/api/multi_filter_select.html
I attempted to add the code from the link above to my current code, as follows:
var $dataTable = $('#example1').DataTable({
"ajax": 'api/tableSearch.php',
"iDisplayLength": 25,
"order": [[ 6, "desc" ]],
"scrollY": 600,
"scrollX": true,
"bDestroy": true,
"columnDefs": [{
"targets": 0,
"render": function (data, type, full, meta){
return '<a class="editLink" href="#">Edit</a><a class="deleteLink" href="#">Del</a>':
}
}], // begin here
initComplete: function(){
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>' )
} );
} );
}
} );
});
I have not received any errors, and the DataTable still loads, but the column search is not there.
I am using jQuery-2.1.3.min, so it should be up to date.
Does anyone see what I am doing wrong and what I can do to correct this issue?
Add a <tfoot> to your table. The expression referencing column.footer() expects it to exist.
What's the problem here? I get the search I want, but it doesn't redraw the table when using the exact match regex column. I'm using a single column to better filter a ranking value that is numeric.
<script>
jQuery(document).ready( function () {
// Setup - add a text input to each header cell
jQuery('#table1 thead tr#filterrow th').each( function () {
var title = jQuery('#table1 thead th').eq( jQuery(this).index() ).text();
jQuery(this).html( '<input type="text" onclick="stopPropagation(event);" placeholder="Search '+title+'" />' );
} );
// Setup - add a text input to each footer cell
jQuery('#table1 tfoot tr#filterrow th').each( function () {
var title = jQuery('#table1 tfoot th').eq( jQuery(this).index() ).text();
jQuery(this).html( '<input type="text" onclick="stopPropagation(event);" placeholder="Search '+title+'" />' );
} );
// DataTable
var table = jQuery('#table1').DataTable( {
orderCellsTop: true,
aLengthMenu: [[-1, 10, 25, 50, 100, 200, 300, 400, 500],[ "All", 10, 25, 50, 100, 200, 300, 400, 500]],
iDisplayLength: -1,
dom: 'B<"lb">lfrtip',
responsive: 'true',
buttons: [
{ extend: 'copy',
oSelectorOpts: {
filter: 'applied'
}
},
{ extend: 'csv',
oSelectorOpts: {
filter: 'applied'
}
},
{ extend: 'pdfHtml5',
oSelectorOpts: {
filter: 'applied'
}
},
{ extend: 'print',
autoPrint: false,
oSelectorOpts: {
filter: 'applied'
}
}
]
} );
// Apply the filter
jQuery("#table1 thead input").on( 'keyup change', function () {
table
.column( jQuery(this).parent().index()+':visible' )
.search(this.value)
.draw();
} );
jQuery("#table1 tfoot input").on( 'keyup change', function () {
table
.column( jQuery(this).parent().index()+':visible' )
.search(this.value)
.draw();
} );
jQuery("#table1 thead input").on( 'keyup change', function () {
table
.column(4)
.search("^" + this.value + "$", true, false, true)
.draw();
} );
jQuery("#table1 tfoot input").on( 'keyup change', function () {
table
.column(4)
.search("^" + this.value + "$", true, false, true)
.draw();
} );
function stopPropagation(evt) {
if (evt.stopPropagation !== undefined) {
evt.stopPropagation();
} else {
evt.cancelBubble = true;
}
}
} );
</script>
I feel like something in my code should be condensed.
The problem is that stopPropagation() method is defined inside ready event handler and is not visible outside of it.
Move definition stopPropagation() outside of ready event handler:
jQuery(document).ready( function () {
// ... skipped ...
});
function stopPropagation(evt) {
if (evt.stopPropagation !== undefined) {
evt.stopPropagation();
} else {
evt.cancelBubble = true;
}
}
NOTES
Since you're using jQuery you could rewrite the same with less code. And the click event handler could be placed inside ready event handler.
You're assigning keyup change twice for each input element in footer and header. Consider rewriting your code as shown in this example.