ColReorder & Individual Column Filtering Positioned In Header

ColReorder & Individual Column Filtering Positioned In Header

Restful Web ServicesRestful Web Services Posts: 202Questions: 49Answers: 2

I know this has been asked before but I cant find a working solution at the moment. I am using a combination of ColReorder, horizontal scrolling and individual column filtering. I cant make the col reorder function work from the top THEAD row and the filtering work from the second THEAD row. Both functions only work if I leave bSortCellsTopas false. However, I need the col reordering to be in the first THEAD row as that is better from a usability point of view.

How I can target the second row in THEAD with this function?

            table.columns().every( function () {
                var that = this;
                $( 'input', this.header() ).on( 'keyup change', function () {
                    if(that.search() !== this.value){
                        that
                        .search( this.value )
                        .draw();
                    }
                });
            }); 

Any help would be greatly appreciated.

Thanks

Chris

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 52,624Questions: 1Answers: 8,049 Site admin

    Hi Chris,

    Probably the easiest way around this is going to be to put the inputs in a footer and then use:

    table.dataTable tfoot {
        display: table-header-group;
    }
    

    to make the footer a header...

    Having said that, using orderCellsTop should work. You'd need to use:

    $( 'input', $('#myTable thead tr:eq(1)') )
    

    to put the input elements into the second row (since column().header() will refer to the header cell DataTables uses.

    Allan

  • Restful Web ServicesRestful Web Services Posts: 202Questions: 49Answers: 2
    edited December 2017

    Hi Allan,

    I had previously tried:

    table.dataTable tfoot {
        display: table-header-group;
    }
    

    However, because I am using horizontal scrolling the <tfoot> element is put in its own <div>element meaning that the CSS rule has no effect, that is my understanding anyway.

    I have also tried your second idea but that didn't work for me either, although I probably made a mistake on my side.

    What has worked for me is to put a 'fake' thead search input bar in the header and simply pass the value entered to the footer search input. Like so:

    $("#filter_t input").keyup(function(event) {
            var id = event.target.id;
            var value = event.target.value;
            $('input#filter_b_'+id).prop("value", value).trigger("change");
    });
    

    Is that an okay-ish solution?

    Thanks

    Chris

  • Restful Web ServicesRestful Web Services Posts: 202Questions: 49Answers: 2

    Hi Allan,

    Thanks for your answer. I did previously attempt the use of:

    table.dataTable tfoot {
        display: table-header-group;
    }
    

    However, because I am also using horizontal scroll I believe that the <tfoot> element is not within the same <div> as the <thead> element and thus cannot be repositioned using CSS, that is my understanding anyway?

    I did try the second suggestion too but to no avail, although that was probably an error on my part.

    What is working for me is quite a rudimentary solution whereby I introduce a 'fake' header input bar at the top and simply pass the values from the thead input to the tfoot input which then carries out the actual filtering.

        $(document).on('keyup change', '#filter_t input', function(){
            var id = event.target.id;
            var value = event.target.value;
            $('input#filter_b_'+id).prop("value", value).trigger("change");
        });
    

    It seems to work okay?

    Chris

  • allanallan Posts: 52,624Questions: 1Answers: 8,049 Site admin

    Ah yes, if you are using scrolling, that CSS hack isn't going to be useful - sorry.

    Just looking at my code above again, it would actually select all input elements in the header - not on a per column basis!

    $( 'input', $('#myTable thead tr:eq(1) th').eq( this.index() ) )
    

    Should be a little better.

    Allan

  • Restful Web ServicesRestful Web Services Posts: 202Questions: 49Answers: 2
    edited December 2017

    Hi Allan,

    I have figured it out now. The problem as far as I understand was I have two columns at the start of my table which I exclude from having functionality like searching and ordering. Therefore my this.index() was always out by 2, i.e. it was 10 when it should have been 8. Secondly, I use the column visibility function to allow the user to show/hide columns, this also seems to affect the index value. So, I dynamically add an id to the thead input upon creation like this:

    $('#t_booking thead #filter_t td:not(.no-filter)').each(function(index){
    var title = $(this).text();
    $(this).html( '<input type="text" placeholder="Search '+ title +'" id="'+ index +'" />' );
     });
    

    Then I perform the search by introducing the colIdxvalue to the function and subtracting 2 from the value to take account of my non searchable columns at the start. I also use the.on() event handler to deal with hidden columns otherwise the search only works on inputs that exist when the page loads which excludes initially hidden columns.

    table.columns().every( function (colIdx) {
     var that = this;
    var id = colIdx-2;
    $(document).on('keyup change', 'input#'+id, function () {
    if(that.search() !== this.value){
    that.search( this.value.replace(/\+/g, '|'), true, false ).draw();
    }
    });
    }); 
    

    Finally, I use stateSave so to restore the search values to the individual columns I do the same:

    var state = table.state.loaded();
    if (state) {
    table.columns().eq(0).each(function (colIdx) {
    var colSearch = state.columns[colIdx].search;
    if (colSearch.search) {
    var id = colIdx-2;
    $('input#'+id).prop("value", colSearch.search.replace(/\|/g, '+'));
    }
    }); 
    table.draw();
    } 
    

    Is their a better way to solve this or does this seem reasonable?

    Thanks

    Chris

  • allanallan Posts: 52,624Questions: 1Answers: 8,049 Site admin
    Answer ✓

    Yes, column visibility would do it, if you are selecting from the document directly, without using a DataTables API method (which in this case you have to since it doesn't provide an API to get the second row of cells in the header...!).

    You can use columns.index() to convert between data index and visible index, which would save you having a "magic" 2 in your code, should you ever change the number of visible columns in future.

    Allan

  • Restful Web ServicesRestful Web Services Posts: 202Questions: 49Answers: 2

    Thanks

This discussion has been closed.