Unable to get filters to work when using server side variables

Unable to get filters to work when using server side variables

kevins1966kevins1966 Posts: 9Questions: 6Answers: 0

I have a .Net 8 core web application page I am having to alter from client side to server side due to data volumes affecting speed.

The DataTable set up below, without the filter row code, works fine and displays data.

However when I attempt to add in the filter row, a 2nd row appears below the header row but with just the column headers displayed as read only as opposed to an input field.

The issue is because the DataTable initiation is replacing

<th><input type="text" placeholder="Search ColumnName" class="column-filter"></th>

with

<th data-dt-column="0" rowspan="1" colspan="1"><div class="dt-column-header"><span class="dt-column-title"><input type="text" placeholder="ColumnName" class="column-filter"></span><span class="dt-column-order"></span></div></th>

I can overcome this by adding the call to "setupFilterRows" inside the "dataSrc" column but that appears to then reset filters when I atttempt to do a search.

Any idea how I can retain the intended element and prevent the default one being created?

Thanks

HTML/Razor Page

<table id="DataGrid" class="table table-striped display" style="width:100%">
    <thead>
    <tr id="header-row"></tr>
    <tr id="filter-row"></tr>
    </thead>
    <tbody></tbody>
</table>

Javascript

    var headersUrl = "/Headers";
    var indexUrl = "/Index";

        var columns = [];

        js.ajax({
            url: headersUrl,
            type: "GET",
            success: function (response) {
                console.log(headersUrl + ": Fetching headers from controller:", headersUrl);
                if (Array.isArray(response.headers) && response.headers.length > 0) {
                    columns = response.headers.map(header => ({ data: header, title: header }));
                } else {
                    console.error(headersUrl + ": success: Unexpected headers format:", response.headers);
                    return;
                }

                console.log(headersUrl + ": success: Headers API Response:", response.headers);

                //Ensure DataTables is only initialized once because, at time of adding, the controller 
                //end points are being called multiple times but I can't work out why
                if (!js.fn.DataTable.isDataTable("#DataGrid")) {

                    console.log("Before DataTable Initialization: check columns structure:", JSON.stringify(columns, null, 2));
                    console.log("Before DataTable Initialization: Does #DataGrid exist?", js("#DataGrid").length);

                    updateHeaderRow(response.headers);
                    setupFilterRows(columns);

                    var table =
                        js('#DataGrid')
                           .DataTable({
                                serverSide: true,
                                processing: true,
                                ajax: {
                                    url: indexUrl,
                                    type: "POST",
                                    headers: { "Content-Type": "application/json" },
                                    data: function (d) {

                                        // Collect filter values
                                        d.Filters = [];
                                        js("#filter-row .column-filter").each(function () {
                                            var columnIndex = js(this).parent().index(); // Get the column index
                                            var value = js(this).val(); // Get the input value
                                            d.Filters.push({ Column: columns[columnIndex].data, Value: value });
                                        });

                                        console.log("data: Filters being sent:", d.Filters); // Debugging

                                        const json = JSON.stringify(d);
                                        console.log(`data: ${indexUrl}: Returned json`, json);
                                        return json;
                                    },
                                    dataSrc: function (response) {
                                        console.log("dataSrc: Data received:", response);
                                        const parsedData = response.data.map(item => JSON.parse(item));
                                        console.log("dataSrc: Parsed Data:", parsedData); // Debugging
                                        return parsedData;
                                    },
                                    error: handleAjaxError
                                },
                                columns: columns,
                                orderCellsTop: true,
                                deferRender: true,
                                initComplete: function () {
                                    console.log("initComplete: Fired");
                                    console.log("initComplete: Checking DataTable API reference:", this.api());
                                    var table = this.api();
                                    setupExportButtons();
                                }
                            });
                }
                console.log("DataTable initialized.");
            },
            error: handleAjaxError
        });

    function setupFilterRows(columns) {
        console.log("setupFilterRows");
        var filterRow = js("#filter-row").empty();

        columns.forEach(column => {
            filterRow.append(`<th><input type="text" placeholder="Search ${column.title}" class="column-filter" /></th>`);
        });

        console.log('filter row: Verify That <thead> Exists and filter row has content', filterRow.html());
        var thCount = js("#filter-row th").length;
        console.log("filter row: Number of <th> elements in #filter-row:", thCount);

    }

    js(document).on("keypress", "#filter-row .column-filter", function (e) {
        if (e.which === 13) { // Enter key
            var columnIndex = js(this).parent().index(); // Get the column index
            var value = js(this).val(); // Get the input value

            console.log(`Filtering column ${columnIndex} with value: ${value}`);

            var table = js("#DataGrid").DataTable();
            table.column(columnIndex).search(value).draw();
        }
    });

Answers

  • kevins1966kevins1966 Posts: 9Questions: 6Answers: 0

    Typically, despite spending hours investigating this, no sooner had I posted this question than I tried a few more experiments and found a post I had not spotted before and that appears to have done the trick.

    I amended that table assignment as shown below.

                        var table =
                            js('#DataGrid')
                                .on("draw.dt", function () {
                                    console.log("Reapplying filter row after table draw...");
    
                                    // Store filter values before re-rendering
                                    var filterValues = {};
                                    js("#filter-row .column-filter").each(function () {
                                        var columnIndex = js(this).parent().index();
                                        filterValues[columnIndex] = js(this).val(); // Store current input value
                                    });
    
                                    setupFilterRows(columns);
    
                                    // Restore filter values after re-rendering
                                    js("#filter-row .column-filter").each(function () {
                                        var columnIndex = js(this).parent().index();
                                        if (filterValues[columnIndex]) {
                                            js(this).val(filterValues[columnIndex]); // Restore previous value
                                        }
                                    });
                                })
                                .DataTable({
                                    serverSide: true,
                                    processing: true,
                                    ajax: {
    
    
Sign In or Register to comment.