'datatables fixed columns with duplicated header for column filtering not fixed
I duplicated my thead row for custom column search according this example
Problem is that I have fixed columns 0 and 1 from left. When I perform scroll right, second row which contains input for column filter is moving but the rest of column is sticky. As I see css, that tr element is missing sticky position as the rest of fixed columns.
How to fix it?
this is my code
$('#custom_list_details thead tr').clone(false)
.addClass('head_filters')
.appendTo('#custom_list_details thead');
custom_list_details_table= $('#custom_list_details').DataTable({
'order': [[1, 'asc']],
"orderCellsTop": true,
'fixedColumns': {
'left': 2
},
"select":true,
"keys": {
"columns": ':not(:first-child)',
"focus": ':eq(2)',
"blurable": false
},
'colReorder': {
'fixedColumnsLeft': 2
},
"ajax": '/customlist_table/'+$custom_list_id+'.json',
"processing": true,
'dom': 'lfr<"pull-right"B>tip',
'buttons': [
{"extend" : 'copyHtml5',"text":"Copy","className": 'btn btn-default btn-xs'},
{"extend" : 'excelHtml5',"text": "XLS","className": 'btn btn-default btn-xs'},
{"extend" : 'csvHtml5',"text": "CSV","className": 'btn btn-default btn-xs'},
{
text: 'Change table size',
className: 'btn btn-primary btn-xs table-size-btn',
action: function ( e, dt, node, config ) {
if ($('#custom_list_details').hasClass('compact') && $('#custom_list_details').hasClass('smaller-table-font'))
{ $('#custom_list_details').removeClass('compact smaller-table-font')}
else { $('#custom_list_details').addClass('compact smaller-table-font')}
}
}
],
"columnDefs": [
{
'targets': 0,
'checkboxes': {
'selectRow': true
}
}
],
"autoWidth":false,
"columns": $columns,
"pageLength": $user_profile_data.table_length,
'lengthMenu': [
[10, 50,100, -1],
[10, 50,100, "All"]
],
"columnDefs": [
{
'targets': 0,
'className': 'center-text',
'checkboxes': {
'selectRow': true
}
}
],
initComplete: function ()
{
$("th[data-column-index='1']").css("background-color","white")
$("th[data-column-index='0']").css("background-color","white")
var api = this.api();
api
.columns()
.eq(0)
.each(function (colIdx) {
if (colIdx > 0) {
// Set the header cell to contain the input element
var cell = $('.head_filters th').eq(
$(api.column(colIdx).header()).index()
);
$(cell).html('<input class="form-control" style="width:100%" type="text" placeholder="" />');
// On every keypress in this input
$(
'input',
$('.head_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);
});
}
else {
var cell = $('.head_filters th').eq(
$(api.column(colIdx).header()).index()
);
$(cell).html('');
}
});
custom_list_details_table.columns.adjust()
//column search end
}
});
Solution 1:[1]
According to DataTables docs about FixedColums:
Additional complexity
It is important to state up front that utilising FixedColumns in your DataTable can significantly increase the complexity of the table and its use should not be undertaken lightly, particularly for complex tables.
Based on that, I don't really know if it's possible to create a second header row and make it FixedColumns compliant, with the normal initialization options.
In Datatables' forum there's a question (a bit old indeed, made in 2016) about a problem with FixedColumns extension and multiple header rows, where the DataTable developer answers:
This ultimately is due to a limitation in DataTables in that you cannot construct complex headers using its initialisation options.
Maybee this kind of issue is still here after 6 years? Don't know :)
That said, I managed to get it work with standard jQuery's DOM manipulation.
I added this drawCallback() in the initialization options, to have column widths recalculated on each draw:
drawCallback: function () {
var api = this.api();
api.columns.adjust();
}
After the table initialization and before the end of $(document).ready() I added a function to get the left CSS value from the fixed cells of the first header row and pass them to the corresponding cells in the second header row:
function cssAdjust(table) {
// get the table header
const header = table.table().header();
// get the 'left' CSS declaration value for first_row-first_column 'th' cell
const col1_CSS_left = $(header)
.find('tr')
.eq(0) // first row
.find('th')
.eq(0) // first column
.css('left');
// apply the found value to the second_row-first_column 'th' cell
$(header)
.find('tr')
.eq(1) // second row
.find('th')
.eq(0) // first column
.css({ left: col1_CSS_left, position: 'sticky' });
// get the 'left' CSS declaration value for first_row-second_column 'th' cell
const col2_CSS_left = $(header)
.find('tr')
.eq(0) // first row
.find('th')
.eq(1) // second column
.css('left');
// apply the found value to the second_row-second_column 'th' cell
$(header)
.find('tr')
.eq(1) // second row
.find('th')
.eq(1) // second column
.css({ left: col2_CSS_left, position: 'sticky' });
table.draw(); // redraw the table
}
After that, always before the end of $(document).ready(), I added a window.resize listener, to avoid messing up widths of columns if the window is resized:
// add eventListener to window resize
window.addEventListener('resize', function () {
cssAdjust(custom_list_details_table);
});
cssAdjust(custom_list_details_table); // <= I immediately call the function to have the fixed double header also in the first table draw;
Here is a codepen with the code: https://codepen.io/cheesyman/pen/NWXXdPO
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
