DotNetRussell
DotNetRussell

Reputation: 9863

Data Table Search is Empty After Refresh but Filter is Active

So I think this might be a bug in the data tables lib. I was able to reproduce this using just their example code in jsfiddle.

Steps to recreate:

  1. Open JS Fiddle link https://jsfiddle.net/t4rphnuc/
  2. Click "Run"
  3. In a footer search box (doesn't matter which) filter the data table
  4. Click "Run" again or refresh the page (you'll need to do steps 2-4 twice because JSFiddle doesn't cache the data table the first time)

NOTE: The Data table still remains filtered but the search fields are now all empty.

Has anyone else seen this or see something I'm doing wrong here?

This is the javascript

<script src="js/jquery.js" type="text/javascript"></script>
<script src="js/jquery.dataTables.js" type="text/javascript"></script>
<script src='https://code.jquery.com/jquery-1.12.4.js'></script>
<script src='https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js' type="text/javascript"></script>
<script src='https://cdn.datatables.net/select/1.2.5/js/dataTables.select.min.js' type="text/javascript"></script>
<script src='https://cdn.datatables.net/buttons/1.5.1/js/dataTables.buttons.min.js' type="text/javascript"></script>
<script src='https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js' type="text/javascript"></script>
<script type="text/javascript">
        $(document).ready(function() {

            const table = $('#example').DataTable({
                stateSave: true
            });

            // Setup - add a text input to each footer cell
            $('#example tfoot th').each( function () {
                var title = $(this).text();
                $(this).html( '<input type="text" placeholder="Search '+title+'" />' );
            } );


            // 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>

Most of the code was taken from this link https://datatables.net/examples/api/multi_filter.html

The expected functionality is that the data table should save state between loads and the search boxes should reload the filtered text when the page reloads.

Upvotes: 5

Views: 7198

Answers (3)

StackNewbie
StackNewbie

Reputation: 11

The above mentioned answers didn't work. So I am posting the solution that works.

                    initComplete: function () {
                                                
                                            this.api()
                                                .columns()
                                                .every(function () {
                                                    let column = this;
                                                    let title = column.footer().textContent;
                                     
                                                    // Create input element
                                                    let input = document.createElement('input');
                                                    input.placeholder = title;
                                                    input.value = column.search();
                                                    input.style.width = '100%';
                                                    column.footer().replaceChildren(input);
                                     
                                                    // Event listener for user input
                                                    input.addEventListener('keyup', () => {
                                                        if (column.search() !== this.value) {
                                                            column.search(input.value).draw();
                                                        }
                                                    });
                                                });
                                        },

input.value = column.search(); should be used at the time of input field creation. This will populate the correct value from the saved state.

Upvotes: 0

DotNetRussell
DotNetRussell

Reputation: 9863

So using a combination of my code and the answer above I came up with this solution

        $(document).ready(function() {
            const table = $('#example').DataTable({
                stateSave: true
            });

            // Setup - add a text input to each footer cell
            $('#example tfoot th').each( function (index,value) {
                var title = $(this).text();
                $(this).html( '<input type="text" placeholder="Search '+title+'" value="'+table.column(index).search()+'"/>' );
            } );


            // 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();
                    }
                } );
            });
        });

The main piece of code here that is the fix is

$(this).html( '<input type="text" placeholder="Search '+title+'" value="'+table.column(index).search()+'"/>' );

By first getting the index value pair while iterating over the columns

$('#example tfoot th').each( function (index,value) 

Then, stealing from the answer above, injecting the search value from the column by index

$(this).html( '<input type="text" placeholder="Search '+title+'" value="'+table.column(index).search()+'"/>' );

Upvotes: 1

colin0117
colin0117

Reputation: 1542

It's because you've got stateSave enabled. This performs the column searches as they were, which are internal to DataTables, but because your input elements are external and DataTables isn't aware of them, you have to populate those yourself. Take a look at this example, it does it in the initComplete:

    // Restore state saved values
    var state = this.state.loaded();
    if (state) {
      var val = state.columns[this.index()];
      input.val(val.search.search);
    }

Upvotes: 6

Related Questions