Crickets
Crickets

Reputation: 524

jQuery Datatables: Combining column visibility with individual column filters (text inputs)?

I am using basic column visibility and individual column searching (text inputs).

The problem is that when the user adds a previously-hidden column to the table, the text field box for that column does not appear. Thus, the user cannot filter that column.

Does anyone know how to enable filters for hidden columns as well? Ideally, this would not cause a byproduct of clearing the text in the other filters (if the user did enter text in the other filters).

Here is my filtering code:

<script type="text/javascript">
$(document).ready(function() {
    // Setup - add a text input to each footer cell
    $('#tableID tfoot th').each( function () {
        var title = $(this).text();

        if ((title != '') && !(title.includes("$"))) {
            // Then the current column is *not* the Action column.          
            $(this).html( '<span style="color: #515151; font-size:15px;"><i>Filter</i></span> <br> <input type="text"  style="margin-top:10px;" placeholder="'+title+'" /> ' );
        }
    } );

    var table = $('#tableID').DataTable();
    // 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();
            }
        });
    } );

} );    
</script>  

I am using this line to hide the columns that I want to be hidden from view by default:

(table.column('.hideCol')).visible(false);

Upvotes: 0

Views: 2053

Answers (2)

Saad Mirza
Saad Mirza

Reputation: 1177

I have worked with this small snippet to hide/Unhide the Individual Column Search, Integrated with Column Visibility Event of Datatables.

$('#table').on( 'column-visibility.dt', function ( e, settings, column, state ) {
            columnv = settings.aoColumns[column].bVisible;
            if(columnv === false){
                 $('#table').find("tr.filters th:eq('"+column+"')").hide();
            }else{
                 $('#table').find("tr.filters th:eq('"+column+"')").show();
            }
        });

Upvotes: 0

Yevhen Horbunkov
Yevhen Horbunkov

Reputation: 15540

There's a custom column-visibility event in DataTables. So, you may revise your <input> elements visibility based on current status of the column.

E.g. you have <input> rendering function, like that:

//function to render input elements
const renderTfootInputs =  () => {
        //grab previous inputs into array
        const prevInputs = [];
        dataTable.columns().every(function(){
            prevInputs.splice(this.index(), 1, $(`#example tfoot [colindex="${this.index()}"]`).val());
        });
        //purge <tfoot> row contents
        $('#example tfoot tr').empty()
        //iterate through table columns
        dataTable.columns().every(function(){
            //if the column is visible
            this.visible() ?
            //append corresponding footer <input>
            $('#example tfoot tr').append(`<th><input colindex="${this.index()}" placeholder="${$(this.header()).text()}" value="${prevInputs[this.index()] || ''}"></input></th>`) :
            true;
        });
};

Than, you may call it upon column visibility changes:

$('#example').on('column-visibility.dt', renderTfootInputs);

Complete demo of this approach might look as follows:

//sample data source
const dataSrc = [
	{id: 1, title: 'apple', cat: 'fruit'},
	{id: 2, title: 'pear', cat: 'fruit'},
	{id: 3, title: 'banana', cat: 'fruit'},
	{id: 4, title: 'carrot', cat: 'vegie'},
	{id: 5, title: 'eggplant', cat: 'vegie'}
];
//datatables initialization
const dataTable = $('#example').DataTable({
	data: dataSrc,
	dom: 'Bfrtip',
	buttons: ['colvis'],
	columns: ['id','title','cat'].map(header => ({title: header, data: header})),
	columnDefs: [
		{targets: 0, visible: false}
	]
});
//append blank footer to the table
$('#example').append('<tfoot><tr></tr></tfoot>');
//function to render input elements
const renderTfootInputs =  () => {
	//grab previous inputs into array
	const prevInputs = [];
	dataTable.columns().every(function(){
		prevInputs.splice(this.index(), 1, $(`#example tfoot [colindex="${this.index()}"]`).val());
	});
	//purge <tfoot> row contents
	$('#example tfoot tr').empty()
	//iterate through table columns
	dataTable.columns().every(function(){
		//if the column is visible
		this.visible() ?
		//append corresponding footer <input>
		$('#example tfoot tr').append(`<th><input colindex="${this.index()}" placeholder="${$(this.header()).text()}" value="${prevInputs[this.index()] || ''}"></input></th>`) :
		true;
	});
};
//initial call of above function
renderTfootInputs();
//call that function each time upon column visibility changes
$('#example').on('column-visibility.dt', renderTfootInputs);
//individual search
$('#example').on('keyup', 'tfoot input', function(event){
	dataTable.column($(event.target).attr('colindex')).search($(event.target).val()).draw();
});
tfoot input {
  display: block;
}

tfoot th {
  padding-left: 10px !important;
}
<!doctype html>
<html>
<head>
  <script type="application/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
  <script type="application/javascript" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
  <script type="application/javascript" src="https://cdn.datatables.net/buttons/1.5.6/js/dataTables.buttons.min.js"></script>
  <script type="application/javascript" src="https://cdn.datatables.net/buttons/1.5.6/js/buttons.colVis.min.js"></script>
  <script type="application/javascript" src="test.js"></script>
  <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
  <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/buttons/1.5.6/css/buttons.dataTables.min.css">
</head>
	<body>
		<table id="example"></table>
	</body>
</html>

Upvotes: 2

Related Questions