Filtering Column Textboxes on Top of DataTable

Filtering Column Textboxes on Top of DataTable

arosnerarosner Posts: 35Questions: 8Answers: 1

Hello,

I have a filtering search textbox at the bottom of each column. I would like to move the search textbox to the top of each column. When I make the following code change, the appearance looks fine. However, the column filtering does not show the appropriate results when executed.

Working code where the filtering is at the bottom:

    $(document).ready(function () {
        bindDatatable();
    });

    function bindDatatable() {
        datatable = $('#tableData')
            .DataTable({
                "dom": "<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'B>>" +
                    "<'row'<'col-sm-12'tr>>" +
                    "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
                "processing": true, // for show progress bar
                "serverSide": false, // for process server side
                "filter": true, // this is to enable filter (search box)
                "pageLength": 10,
                "ajax": {
                    "url": "/DataManipulation/LoadBudgetFunctionDescription",
                    "type": "POST",
                    "datatype": "json"
                },
                "language": {
                    "emptyTable": "No record found.",
                    "processing":
                        '<i class="fa fa-spinner fa-spin fa-3x fa-fw" style="color:#2a2b2b;"></i><span class="sr-only">Loading...</span> '
                },
                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;
                            column.footer().replaceChildren(input);

                            // Event listener for user input
                            input.addEventListener('change', () => {
                                if (column.search() !== this.value) {
                                    column.search(input.value).draw();
                                }
                            });
                        });
                },
                "columns": [
                    {
                        "data": "AGYBFC",
                        "autoWidth": true,
                        "searchable": true,
                    },
                    {
                        "data": "AGENCY",
                        "autoWidth": true,
                        "searchable": true,
                    },
                    {
                        "data": "BFCODE",
                        "autoWidth": true,
                        "searchable": true,
                    },
                    {
                        "data": "BUDFUNCNAM",
                        "autoWidth": true,
                        "searchable": true,
                    },
                    {
                        "data": "BUDFUNCDES",
                        "autoWidth": true,
                        "searchable": true,
                    },
                ]
            });

To move the filtering textboxes to the bottom, I modify the following lines of code in the initComplete function:

  • let title = column.footer().textContent; to let title = column.header().textContent;
  • column.footer().replaceChildren(input); to column.header().replaceChildren(input);

As I mentioned above, the visual is fine, but the results do not get filtered properly when executing the filter.

Thank you!

Answers

  • kthorngrenkthorngren Posts: 21,171Questions: 26Answers: 4,922

    Its difficult to debug just your code snippet. We will need to see a running test case showing the issue to help debug.
    https://datatables.net/manual/tech-notes/10#How-to-provide-a-test-case

    Maybe this example will help.

    Kevin

  • arosnerarosner Posts: 35Questions: 8Answers: 1
    edited February 9

    Hi Kevin,

    I noticed the example, but I was not interested in a fixed header nor filtering with each keystroke. Also, I have an ajax call which will be difficult to replicate in the test system provided. Does the page source help?

    Regards,

    Al

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>BudgetFunctionDescription - My ASP.NET Application</title>
        <script src="/Scripts/modernizr-2.8.3.js"></script>
    
        
        <link href="https://cdn.datatables.net/1.13.7/css/jquery.dataTables.min.css" rel="stylesheet" type="text/css" />
        <style type="text/css">
            tfoot input {
                width: 100%;
                padding: 3px;
                box-sizing: border-box;
            }
    
            .cell-input-class {
                padding: 3px 3px;
                border: 1px solid #ccc;
                border-radius: 2px;
                width: 100%;
                height: 250px;
            }
        </style>
    
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
    
        <script type="text/javascript" language="javascript" src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
    </head>
    <body>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-dark bg-dark">
            <div class="container">
                <a class="navbar-brand" href="/">Application name</a>
                <button type="button" class="navbar-toggler" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" title="Toggle navigation" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li><a class="nav-link" href="/">Home</a></li>
                    </ul>
                </div>
                <div class="collapse navbar-collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li><a class="navbar-brand" href="/Tables">Database Table</a></li>
                    </ul>
                </div>
                <div class="collapse navbar-collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li><a class="navbar-brand" href="/DataManipulation">Data Manipulation</a></li>
                    </ul>
                </div>
            </div>
        </nav>
        <div class="container body-content">
            
    
    
    <h4>
        <label for="Budget_Function_Description">Budget Function Description</label>
        <p style="color:red;"></p>
    </h4>
    <br />
    <h4>Data</h4>
    <table id="tableData" class="display compact" style="width:100%">
        <thead>
            <tr>
                <th>AGYBFC</th>
                <th>AGENCY</th>
                <th>BFCODE</th>
                <th>BUDFUNCNAM</th>
                <th style="color: #008000;">BUDFUNCDES (Click on text to edit)</th>
            </tr>
        </thead>
        <tfoot>
            <tr>
                <th>AGYBFC</th>
                <th>AGENCY</th>
                <th>BFCODE</th>
                <th>BUDFUNCNAM</th>
                <th>BUDFUNCDES</th>
            </tr>
        </tfoot>
    </table>
    
    
    
    
            <hr />
            <footer>
                <p>&copy; 2024 - My ASP.NET Application</p>
            </footer>
        </div>
    
        <script src="/Scripts/jquery-3.4.1.js"></script>
    
        
        <script type="text/javascript" language="javascript" src="https://code.jquery.com/jquery-3.7.0.js"></script>
        <script type="text/javascript" language="javascript" src="https://cdn.datatables.net/1.13.7/js/jquery.dataTables.min.js"></script>
        <script>
            $(document).ready(function () {
                bindDatatable();
            });
    
            function bindDatatable() {
                datatable = $('#tableData')
                    .DataTable({
                        "dom": "<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'B>>" +
                            "<'row'<'col-sm-12'tr>>" +
                            "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
                        "processing": true, // for show progress bar
                        "serverSide": false, // for process server side
                        "filter": true, // this is to enable filter (search box)
                        "pageLength": 10,
                        "ajax": {
                            "url": "/DataManipulation/LoadTest",
                            "type": "POST",
                            "datatype": "json"
                        },
                        "language": {
                            "emptyTable": "No record found.",
                            "processing":
                                '<i class="fa fa-spinner fa-spin fa-3x fa-fw" style="color:#2a2b2b;"></i><span class="sr-only">Loading...</span> '
                        },
                        initComplete: function () {
                            this.api()
                                .columns()
                                .every(function () {
                                    let column = this;
                                    **let title = column.header().textContent;**
    
                                    // Create input element
                                    let input = document.createElement('input');
                                    input.placeholder = title;
                                    **column.header().replaceChildren(input);**
    
                                    // Event listener for user input
                                    input.addEventListener('change', () => {
                                        if (column.search() !== this.value) {
                                            column.search(input.value).draw();
                                        }
                                    });
                                });
                        },
                        "columns": [
                            {
                                "data": "AGYBFC",
                                "autoWidth": true,
                                "searchable": true,
                            },
                            {
                                "data": "AGENCY",
                                "autoWidth": true,
                                "searchable": true,
                            },
                            {
                                "data": "BFCODE",
                                "autoWidth": true,
                                "searchable": true,
                            },
                            {
                                "data": "BUDFUNCNAM",
                                "autoWidth": true,
                                "searchable": true,
                            },
                            {
                                "data": "BUDFUNCDES",
                                "autoWidth": true,
                                "searchable": true,
                            },
                        ]
                    });
            }
        </script>
    
    </body>
    </html>
    

    Edited by Kevin: Syntax highlighting. Details on how to highlight code using markdown can be found in this guide

  • kthorngrenkthorngren Posts: 21,171Questions: 26Answers: 4,922
    edited February 9

    The example will work whether or not FixedHeader is used. You can remove the keyup event if you only want to search on change. The data source doesn't matter for this solution. You can build a test case using an Ajax data source. See all the options in this technote.

    I may be missing it but I don't see where you are applying the search inputs to the header. If you want help with your solution please buiild a simple test case showing us what you are doing. You can start with this basic Ajax template:
    https://live.datatables.net/dodobuge/1/edit

    Kevin

  • kthorngrenkthorngren Posts: 21,171Questions: 26Answers: 4,922

    Here is another example with search inputs in the header. Note the use of orderCells Top to move the sorting events to the top header row.
    https://live.datatables.net/giharaka/1/edit

    Kevin

  • kthorngrenkthorngren Posts: 21,171Questions: 26Answers: 4,922

    I would guess the problem with your code is the selector used for the vent handler. Have you verified if the change event fires when using the search inputs?

    Kevin

Sign In or Register to comment.