Column Search Third Header

Column Search Third Header

rf1234rf1234 Posts: 3,000Questions: 87Answers: 421
edited May 2019 in DataTables

I am trying to get column search work with three headers:
1. Labels and ordering
2. Search Input
3. Select / Dropdown

For 2. and 3. there are examples in the docs but only for the footer. I found something somewhere to make 2. run and it works perfectly fine!

My problem is still with 3. I tried to adapt the code from the footer example and also found some hints elsewhere but the result is not good at all.

I have the following problems:
1. I can't get the Select Input into the third row. Either it sits in the first row and overwrites the labels or I have a third row just with labels and no input.
2. The Select dropdown only works for fields that don't have a lot of client side rendering. For fields from mJoins with a lot of rendering it is just [Object object]. So initComplete doesn't seem to be after rendering and hence does not work for these kind of fields?!

I have attached a screenshot highlighting the issue and part of my oode. Any ideas?
@kthorngren I think you could have a solution for this, Kevin. Or @allan and @colin maybe?

var ctrTable = $('#tblCtrManagement').DataTable({
    dom: 'Bfrltip', 
    processing: false,
    serverSide: serverSide,    //server side only works well with type "POST" !!!
    scrollX: scrollX,
    responsive: responsive,
    orderCellsTop: true,
    initComplete: function () {
        if ( ( ! ctrMgmtServerSidePage ) && ( ! inboxExpPage ) ) {
            var api = this.api();
            // Setup - add a text input to each header cell
            $('.filterHead', api.table().header()).each( function () {
                var title = (lang === 'de' ? 'Suche ' : 'Search ') + $(this).text();
                $(this).html( '<input type="text" placeholder="'+title+'" class="column_search text-muted"/>' );
            } );
            this.api().columns().every( function () {
                var column = this;
                var select = $('<select><option value=""></option></select>')
                    .appendTo( $('table thead tr:eq(2) th:eq(' + column.index() + ')').empty() )
//                    .appendTo( $(column.header('.filterSelect')).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>' )
                } );
            } );
        }
    },
if ( ( ! ctrMgmtServerSidePage ) && ( ! inboxExpPage ) ) {
    // Apply the search
    $( 'table thead'  ).on( 'keyup', ".column_search", function () {   
        ctrTable
            .column( $(this).parent().index() )
            .search( this.value )
            .draw();
    } );
}
<div class="container">
    <div id="ctrManagementHeader" class="ctrManagementPage">
        <h3 style="text-align:justify"><span class="ctrManagementHeader"><?php echo $en?('Your Contracts'):('Ihre Verträge');?></span></h3>
    </div>
    <?php require_once 'contractTimeSelector.php'; ?>
    <table id="tblCtrManagement" class="table table-striped table-bordered ctrManagementPage"
           cellspacing="0" width="100%">
        <thead>
            <tr>
                <th class="noSelectCols"><?php echo $en?('Name,<br>Purpose'):('Bezeichnung,
Verwendungszweck');?></th> <th><?php echo $en?('Departments'):('Abteilungen');?></th> <th><?php echo $en?('Category Values'):('Kategoriewerte');?></th> <th><?php echo $en?('Labels'):('Labels');?></th> <th><?php echo $en?('Contract Number'):('Vertragsnummer');?></th> <th class="all"><?php echo $en?('Serial'):('Laufende Nummer');?></th> <th><?php echo $en?('Start Date'):('Beginn');?></th> <th><?php echo $en?('End Date'):('Ende');?></th> <th><?php echo $en?('Annual Costs(-) / Income'):('Jährl. Kosten(-) / Ertrag');?></th> <th><?php echo $en?('VAT Status'):('USt.-Status');?></th> <th><?php echo $en?('Expiration Follow Up'):('Erinnerung vor Ablauf');?></th> <th class="noSelectCols all cnt">Info</th> <!--all = column never hidden--> <th class="noSelectCols all"><?php echo $en?('Documentation'):('Dokumentation');?></th> <!--all = column never hidden--> <th class="never" id="doneCheckBox"><?php echo $en?('done'):('erledigt');?></th> <th class="none"><?php echo $en?('Last update'):('Letzte Änderung');?></th> <th class="hiddenCols" id="updateTime"><?php echo $en?('Update Time'):('geändert am');?></th> <th class="never"></th> </tr> <tr> <th class="filterHead"><?php echo $en?('Name,<br>Purpose'):('Bezeichnung,
Verwendungszweck');?></th> <th class="filterHead"><?php echo $en?('Departments'):('Abteilungen');?></th> <th class="filterHead"><?php echo $en?('Category Values'):('Kategoriewerte');?></th> <th class="filterHead"><?php echo $en?('Labels'):('Labels');?></th> <th class="filterHead"><?php echo $en?('Contract Number'):('Vertragsnummer');?></th> <th class="filterHead all"><?php echo $en?('Serial'):('Laufende Nummer');?></th> <th class="filterHead"><?php echo $en?('Start Date'):('Beginn');?></th> <th class="filterHead"><?php echo $en?('End Date'):('Ende');?></th> <th class="filterHead"><?php echo $en?('Annual Costs(-) / Income'):('Jährl. Kosten(-) / Ertrag');?></th> <th class="filterHead"><?php echo $en?('VAT Status'):('USt.-Status');?></th> <th class="filterHead"><?php echo $en?('Expiration Follow Up'):('Erinnerung vor Ablauf');?></th> <th class="noSelectCols all cnt">Info</th> <!--all = column never hidden--> <th class="noSelectCols all"><?php echo $en?('Documentation'):('Dokumentation');?></th> <!--all = column never hidden--> <th class="never"><?php echo $en?('done'):('erledigt');?></th> <th class="none"><?php echo $en?('Last update'):('Letzte Änderung');?></th> <th class="hiddenCols"><?php echo $en?('Update Time'):('geändert am');?></th> <th class="never"></th> </tr> <tr> <th class="filterSelect"><?php echo $en?('Name,<br>Purpose'):('Bezeichnung,
Verwendungszweck');?></th> <th class="filterSelect"><?php echo $en?('Departments'):('Abteilungen');?></th> <th class="filterSelect"><?php echo $en?('Category Values'):('Kategoriewerte');?></th> <th class="filterSelect"><?php echo $en?('Labels'):('Labels');?></th> <th class="filterSelect"><?php echo $en?('Contract Number'):('Vertragsnummer');?></th> <th class="filterSelect all"><?php echo $en?('Serial'):('Laufende Nummer');?></th> <th class="filterSelect"><?php echo $en?('Start Date'):('Beginn');?></th> <th class="filterSelect"><?php echo $en?('End Date'):('Ende');?></th> <th class="filterSelect"><?php echo $en?('Annual Costs(-) / Income'):('Jährl. Kosten(-) / Ertrag');?></th> <th class="filterSelect"><?php echo $en?('VAT Status'):('USt.-Status');?></th> <th class="filterSelect"><?php echo $en?('Expiration Follow Up'):('Erinnerung vor Ablauf');?></th> <th class="noSelectCols all cnt">Info</th> <!--all = column never hidden--> <th class="noSelectCols all"><?php echo $en?('Documentation'):('Dokumentation');?></th> <!--all = column never hidden--> <th class="never"><?php echo $en?('done'):('erledigt');?></th> <th class="none"><?php echo $en?('Last update'):('Letzte Änderung');?></th> <th class="hiddenCols"><?php echo $en?('Update Time'):('geändert am');?></th> <th class="never"></th> </tr> </thead> </table> </div>

Replies

  • colincolin Posts: 15,240Questions: 1Answers: 2,599

    Hi @rf1234 ,

    This here should do the trick - it's got input in the middle row, then selects in the bottom.

    Hope that helps,

    Colin

  • rf1234rf1234 Posts: 3,000Questions: 87Answers: 421

    Thanks a lot Colin! That's exactly what I need!! :)

    Do you have a library with more use cases like this? Is it public? It it possible to link it to the examples in the docs? Or make it available otherwise?

    That is the only thing I dislike about Data Tables: Not enough examples ... I am not a front end developer and without examples I am lost pretty much ...

  • colincolin Posts: 15,240Questions: 1Answers: 2,599

    Hi @rf1234 ,

    No, I just glued together the existing examples for this one - this and this. We're looking at doing a public wiki which will group topics together, with examples in those topic's threads consolidated and easier to find.

    Glad it helped,

    Cheers,

    Colin

  • rf1234rf1234 Posts: 3,000Questions: 87Answers: 421

    Hi Colin,

    I implemented your solution - and unfortunately it didn't work. I tried everything but couldn't get it running. I think it might be a problem because I use ScrollX ?!

    I reverted back to this solution which works for search inputs. Would you be able to suggest something similar for the select inputs as well?

    var ctrTable = $('#tblCtrManagement').DataTable({
        dom: 'Bfrltip', 
        processing: false,
        serverSide: false,    //server side only works well with type "POST" !!!
        scrollX: true,
        responsive: false,
        orderCellsTop: true,
        initComplete: function () {
            if ( ( ! ctrMgmtServerSidePage ) && ( ! inboxExpPage ) ) {
                var table = this.api();
                // Setup - add a text input to each header cell
                $('.filterHead', table.table().header()).each( function () {
                    var title = (lang === 'de' ? 'Suche ' : 'Search ') + $(this).text();
                    $(this).html( '<input type="text" placeholder="'+title+'" class="column_search text-muted"/>' );
                } );
            }
        },
    
    if ( ( ! ctrMgmtServerSidePage ) && ( ! inboxExpPage ) ) {
        // Apply the search
        $( 'table thead'  ).on( 'keyup', ".column_search", function (e) {   
            var code = e.which;
            if ( code == 13 ) { //enter key
                e.preventDefault();
            }
            //8: backspace, 13: enter, 32: space, 59 or 186: semi-colon,
            //188: comma, 189: dash or minus, 190: period
            if ( code == 32 || code == 13 || code == 8 || code == 59 || 
                 code == 186 || ( code > 187 && code < 191 )            ){
                ctrTable
                    .column( $(this).parent().index() )
                    .search( this.value )
                    .draw();
            }
        } );
    }
    
    <div class="container">
        <div id="ctrManagementHeader" class="ctrManagementPage">
            <h3 style="text-align:justify"><span class="ctrManagementHeader"><?php echo $en?('Your Contracts'):('Ihre Verträge');?></span></h3>
        </div>
        <?php require_once 'contractTimeSelector.php'; ?>
        <table id="tblCtrManagement" class="table table-striped table-bordered ctrManagementPage"
               cellspacing="0" width="100%">
            <thead>
                <tr>
                    <th class="noSelectCols"><?php echo $en?('Name,<br>Purpose'):('Bezeichnung,
    Verwendungszweck');?></th> <th><?php echo $en?('Departments'):('Abteilungen');?></th> <th><?php echo $en?('Category Values'):('Kategoriewerte');?></th> <th><?php echo $en?('Labels'):('Labels');?></th> <th><?php echo $en?('Contract Number'):('Vertragsnummer');?></th> <th class="all"><?php echo $en?('Serial'):('Laufende Nummer');?></th> <th><?php echo $en?('Start Date'):('Beginn');?></th> <th><?php echo $en?('End Date'):('Ende');?></th> <th><?php echo $en?('Annual Costs(-) / Income'):('Jährl. Kosten(-) / Ertrag');?></th> <th><?php echo $en?('VAT Status'):('USt.-Status');?></th> <th><?php echo $en?('Expiration Follow Up'):('Erinnerung vor Ablauf');?></th> <th class="noSelectCols all cnt">Info</th> <!--all = column never hidden--> <th class="noSelectCols all"><?php echo $en?('Documentation'):('Dokumentation');?></th> <!--all = column never hidden--> <th class="never" id="doneCheckBox"><?php echo $en?('done'):('erledigt');?></th> <th class="none"><?php echo $en?('Last update'):('Letzte Änderung');?></th> <th class="hiddenCols" id="updateTime"><?php echo $en?('Update Time'):('geändert am');?></th> <th class="never"></th> </tr> <tr> <td class="filterHead"><?php echo $en?('Name,<br>Purpose'):('Bezeichnung,
    Verwendungszweck');?></td> <td class="filterHead"><?php echo $en?('Departments'):('Abteilungen');?></td> <td class="filterHead"><?php echo $en?('Category Values'):('Kategoriewerte');?></td> <td class="filterHead"><?php echo $en?('Labels'):('Labels');?></td> <td class="filterHead"><?php echo $en?('Contract Number'):('Vertragsnummer');?></td> <td class="filterHead all"><?php echo $en?('Serial'):('Laufende Nummer');?></td> <td class="filterHead"><?php echo $en?('Start Date'):('Beginn');?></td> <td class="filterHead"><?php echo $en?('End Date'):('Ende');?></td> <td class="filterHead"><?php echo $en?('Annual Costs(-) / Income'):('Jährl. Kosten(-) / Ertrag');?></td> <td class="filterHead"><?php echo $en?('VAT Status'):('USt.-Status');?></td> <td class="filterHead"><?php echo $en?('Expiration Follow Up'):('Erinnerung vor Ablauf');?></td> <td class="noSelectCols all cnt">Info</td> <!--all = column never hidden--> <td class="noSelectCols all"><?php echo $en?('Documentation'):('Dokumentation');?></td> <!--all = column never hidden--> <td class="never"><?php echo $en?('done'):('erledigt');?></td> <td class="none"><?php echo $en?('Last update'):('Letzte Änderung');?></td> <td class="hiddenCols"><?php echo $en?('Update Time'):('geändert am');?></td> <td class="never"></td> </tr> </thead> </table> </div>
  • rf1234rf1234 Posts: 3,000Questions: 87Answers: 421
    edited May 2019

    Your example works with ScrollX ... No idea what the problem really is.

  • colincolin Posts: 15,240Questions: 1Answers: 2,599

    Could you link to that page with the problems? Also, you haven't said what the problem is - is it drawing fine but the search not filtering out records? As you say, mine is working, so we really need to see yours running to see what the issue is.

    C

  • kthorngrenkthorngren Posts: 21,344Questions: 26Answers: 4,954

    Maybe this thread will help regarding scrollX:
    https://datatables.net/forums/discussion/comment/141980#Comment_141980

    This is my example based on that thread:
    http://live.datatables.net/saqozowe/70/edit

    As Colin says if this doesn't help please post an example.

    Kevin

  • rf1234rf1234 Posts: 3,000Questions: 87Answers: 421

    Sorry, no I can't link the page.

    The problem is that there are only two small lines under the header line with zero content. I tried to develop something along the lines of the functioning search input solution and I also managed to make the select fields visible but then I couldn't load the contents of the select field ...

  • rf1234rf1234 Posts: 3,000Questions: 87Answers: 421

    Let me try Kevin's solution now. Maybe I get this running. Many thanks, guys!

  • rf1234rf1234 Posts: 3,000Questions: 87Answers: 421
    edited May 2019

    Kevin, many thanks. It worked right away!!!

    Only one small problem left. As mentioned in my first post the field values BEFORE rendering seem to be loaded into the options of the select field.

    If there is an array of objects coming from the server as in an Mjoin it doesn't work at all. [object Object] is being displayed in the dropdown.

    If it is 0 or 1 for boolean false or true the problem is that you can't choose between the rendered values but only between 0 and 1.

    Is there any way to load the field values AFTER rendering?

  • kthorngrenkthorngren Posts: 21,344Questions: 26Answers: 4,954

    Since this code is in initComplete it is run after the rendering the table. You are effectively using column().data() to get the data for the drop down. This is the original data. You might be able to use cell().render() instead to get the rendered data. Not sure if or how to incorporate that at the moment. I don't have an example.

    Otherwise you will need to handle the different data structures within the column.data().unique().sort().each() loop. The easiest way would be to know the column index (i) and with an if statement execute different code to build the selects. To make it more flexible you might be able to use different classes for different types of data structures. Lots of options to do this :smile: Don't have an example though.

    Kevin

  • rf1234rf1234 Posts: 3,000Questions: 87Answers: 421

    It was pretty hard to add the same class name for every cell in one column but eventually I got it done with rowCallback. Then I only had to replace column.data() with column.cells().render()

    So this code works now:

    var ctrTable = $('#tblCtrManagement').DataTable({
        dom: 'Bfrltip', 
        processing: false,
        serverSide: serverSide,    //server side only works well with type "POST" !!!
        scrollX: scrollX,
        responsive: responsive,
        orderCellsTop: true,
        initComplete: function () {
            if ( ( ! ctrMgmtServerSidePage ) && ( ! inboxExpPage ) ) {
                var table = this.api();
                // Setup - add a text input to each header cell
                $('.filterHead', table.table().header()).each( function () {
                    var title = (lang === 'de' ? 'Suche ' : 'Search ') + $(this).text();
                    $(this).html( '<input type="text" placeholder="'+title+'" class="column_search text-muted"/>' );
                } );
                $('.filterSelect', table.table().header()).each( function (i) {
    //                $(this).addClass('flt'+ i);
                    var column = table.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.cells('.flt'+ i).render('display').unique().sort().each( function ( d, j ) {
                        select.append( '<option value="'+d+'">'+d+'</option>' );
                    } );
                } );
            }
        },
    

    and the row callback. "ixUpdateTime" being the index of the last column of the table.

    rowCallback: function (row, data) {
        var i;
        for ( i=0; i < ixUpdateTime; i++ ) {
            $('td:eq('+i+')', row).addClass('flt'+ i);
        }
    }
    
  • rf1234rf1234 Posts: 3,000Questions: 87Answers: 421

    Thanks again Kevin @ktorngren and Colin @colin !!

    I got it finished and polished by now - and I m very grateful for your help.

    If anyone is in need of the final version of my code just let me know.

  • kthorngrenkthorngren Posts: 21,344Questions: 26Answers: 4,954

    Glad you got it working.

    Kevin

This discussion has been closed.