Select filters moving along columns

Select filters moving along columns

silkspinsilkspin Posts: 141Questions: 32Answers: 5

I'm using select filters with columns that can be hidden, but this is causing them to move along when the columns are toggled off. I'm guessing the problem is with the function buildSelect .columns([1,2]). The select filters move to columns 3 and 4 when the Toggle Columns button Position/Office is clicked (which hides both columns). I tried using column names but that didn't work. Is it possible to stop this happening? http://live.datatables.net/pusaxiyu/1/edit

This question has accepted answers - jump to:

Answers

  • kthorngrenkthorngren Posts: 20,332Questions: 26Answers: 4,774

    Does this thread help? Its a similar question you asked before.

    Kevin

  • silkspinsilkspin Posts: 141Questions: 32Answers: 5

    It's funny you should mentioned that Kevin! I'd already referred back to that version which does work fine on my local dev and your test case. However, when I tried to get it working with this different version I didn't have any luck. I thought it might be down to the different way of hiding columns and not using colvis. I've added that code back in the test case to show it doesn't seem to work. http://live.datatables.net/pusaxiyu/1/edit. Does anything look wrong to you?

  • allanallan Posts: 61,744Questions: 1Answers: 10,111 Site admin

    Here is a little update to your code, but I'm not sure it is exactly what you are looking for: http://live.datatables.net/pusaxiyu/4/edit .

    In it the Position and Office columns are the only ones with select filters - is that what you want. When they are hidden, the filters go as well.

    The key thing here is to know that DataTables doesn't support multiple thead elements like you had in your HTML. It simply doesn't keep track of any but the first. So you need to have a single thead, but it can have multiple rows.

    Allan

  • silkspinsilkspin Posts: 141Questions: 32Answers: 5

    Sorry about the multiple thead Allan. They weren't in my dev version so I must've overlooked them whilst testing. Your version does function like I was expecting it to. The filters are hidden when the columns are hidden and the cascading filtering works too.

    However, my dev version is different which might be causing the problems. It's based on a tutorial I followed to pull a CSV in using Ajax. Up to now it's worked fine with the different versions of DT I've done so I think the code structure is OK, but you might tell me otherwise. The placing of this code gives different results...

      table.on( 'draw', function () {
        buildSelect( table );
      } );
    

    I've added comments above the 2 locations I've tried this code, and what the results were. Can you spot anything wrong with this simplified edited code?

    $(document).ready(function() {
    
      var table;
      
      // build cascading select
      function buildSelect( table ) {
        table
        .columns([1,2])
        .every( function () {
          var column = this;
          var select = $('<select class="custom-select><option value=""></option></select>')
          .appendTo( $("thead tr:eq(1) th").eq(column.index()).empty() )
          .on( 'change', function () {
            var val = $.fn.dataTable.util.escapeRegex($(this).val());
            column
            .search( val ? '^' + val + '$' : '', true, false ).draw();
          });
    
          table
          .cells( null, column.index(), {search: 'applied'})
          .render('filter')
          .unique()
          .sort()
          .each( function ( d, j ) {
            select.append( '<option value="' + d + '">' + d + '</option>' );
          });
          // The rebuild will clear the exisiting select, so it needs to be repopulated
          var currSearch = column.search();
          if ( currSearch ) {
            select.val( currSearch.substring(1, currSearch.length-1).replace(/\\(.)/g, '$1') );
          }
        });
      }
    
      $.ajax({
        url: "import.php",
        method: "POST",
        data: formdata,
        dataType: "json",
        contentType: false,
        cache: false,
        processData: false,
        success: function(jsonData) {
          $("#csv_file").val("");
    
          table = $("#datatable").DataTable({
    
            orderCellsTop: true,
            dom: 'lBfrtp',
        
            buttons: [
              // grouped column toggles
              { 
                text: 'Toggle Columns',
                extend: 'collection',
                buttons: [
                  { 
                    text: 'Name',
                    className: 'active',
                    extend: 'columnToggle',
                    columns: [0]
                  },
                  { 
                    text: 'Position/Office',
                    className: 'active',
                    extend: 'columnToggle',
                    columns: [1,2]
                  },
                  { 
                    text: 'Age/Start Date',
                    className: 'active',
                    extend: 'columnToggle',
                    columns: [3,4]
                  },
                ]
              },
              // show all columns to on
              {
                text: 'Show All Columns',
                className: 'hide-button show-all-columns',
                extend: 'columnVisibility',
                visibility: true
              },
            ],
    
            initComplete: function() {
              buildSelect( this.api() );
            }, 
            
          }); // END OF #datatable
    
          
          // ************************************************  
          // IF PLACED HERE CASCADING FILTERS WORK
          // BUT THE FILTERS MOVE ALONG WHEN THE COLUMNS ARE HIDDEN
          // ************************************************
          table.on( 'draw', function () {
            buildSelect( table );
          } );
          
          
          // clear filters on hidden columns
          $('#datatable').on( 'column-visibility.dt', function ( e, settings, column, state ) {
    
            if ( !state ) {
              table.columns(column).search('').draw();
            }
            
            table.columns([1,2])
              .every( function () {
              var idx = this.index('visible');
              if (this.search() === '' && idx !== null) {
                $('#datatable thead tr:eq(1) th:eq('+idx+') select').val('');
              }
            });
          } );
          
        },
      }); // END OF $.ajax
    
      
      // ************************************************
      // IF PLACED HERE THE FILTERS DISAPPEAR AS EXPECTED WHEN THE COLUMNS ARE HIDDEN
      // BUT CASCADING FILTERS DON'T WORK
      // ************************************************
      table.on( 'draw', function () {
        buildSelect( table );
      } );
    
    
    });
    
    
  • allanallan Posts: 61,744Questions: 1Answers: 10,111 Site admin

    Drop all of your calls to buildSelect other than that in initComplete. You shouldn't need to regenerate the select dropdowns.

    Allan

  • silkspinsilkspin Posts: 141Questions: 32Answers: 5

    Hi Allan. I've done that and now the cascading doesn't work. buildSelect( table ); on line 98 does call the function and that works, it's just then the filters on column hiding move to the next 2 columns.

  • kthorngrenkthorngren Posts: 20,332Questions: 26Answers: 4,774
    edited October 2020

    I removed the second thead from your example as Allan noted and added orderCellsTop. Since you aren't looping through all the columns to update the selects you first need to remove all of them, my example uses this code:

        $("thead tr:eq(1) td").each( function () {
          $(this).empty();
        });
    

    You then need to use column.index('visible'); to get the proper index to apply the select input:

          var visIndex = column.index('visible');
          
          var select = $('<select><option value=""></option></select>')
          .appendTo( $("thead tr:eq(1) td").eq( visIndex ).empty() )
    

    I also added another toggle group for Name to see this work.

    http://live.datatables.net/pusaxiyu/5/edit

    Kevin

  • silkspinsilkspin Posts: 141Questions: 32Answers: 5

    Hi Kevin. I've just looked at your test case but if "Position/Office" is toggled off the Office filter moves over to the top of the Name column. Cascading still seems to work though.

  • kthorngrenkthorngren Posts: 20,332Questions: 26Answers: 4,774
    edited October 2020

    Ok. so if the column isn't visible then the column.index('visible'); is null. I added an if statement to test for this:
    http://live.datatables.net/pusaxiyu/6/edit

    Kevin

  • silkspinsilkspin Posts: 141Questions: 32Answers: 5

    Unfortunately filters are still moving around the columns. I did have a working version of this from a few weeks ago which you kindly helped with. The main difference with this version though, is the toggling of multiple columns at once which seems to be the sticking point. This version extends columnToggle whereas the single column toggle used colvis which worked fine.

  • kthorngrenkthorngren Posts: 20,332Questions: 26Answers: 4,774
    Answer ✓

    Unfortunately filters are still moving around the columns.

    Are you saying that my example has this problem? If so please provide the steps to recreate.

    I forgot to mention that I changed the toggle groups to pair position with age and office with start date to show this a bit better.

    Kevin

  • kthorngrenkthorngren Posts: 20,332Questions: 26Answers: 4,774
    edited January 15 Answer ✓

    I added back your original toggle pairs along with mine:
    http://live.datatables.net/pusaxiyu/7/edit

    Updated example:
    https://live.datatables.net/pusaxiyu/66/edit

    Kevin

  • silkspinsilkspin Posts: 141Questions: 32Answers: 5
    edited October 2020

    Ah, that's why I thought they were jumping around a bit!

    I've just transferred your changes to my dev version and after initial testing it all looks OK. Thank you very much for getting to the bottom of the problem again Kevin!

This discussion has been closed.