Unable to get filters to work when using server side variables
Unable to get filters to work when using server side variables

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