我正在使用 DataTables 来管理一个表,其中某些内容位于可折叠的
<tr>
元素中。最初,这些 <tr>
是隐藏的(显示:无),只有当按下相应的按钮 (Details
) 时它们才变得可见。
使用 DataTables 搜索过滤器时,我希望表格显示包含隐藏
<tr>
元素中的匹配内容的主行,而不要求用户先单击“Details
”按钮。
这是我当前的设置:
每个可折叠行都有一个唯一的 ID,我将每行的内容存储在具有以下结构的字典中: { 'id_of_row': ['内容1', '内容2', '内容3', ...] } 目标是当用户在搜索框中键入内容时在字典中进行搜索,如果在任何字典元素中找到匹配项,则会使用 id_of_row 并应显示具有该 id 的相应主行。
示例问题:
如果我搜索术语“requ”,则不会显示任何内容,因为相应的内容位于折叠的
<tr>
内。但是,如果我通过单击“详细信息”按钮手动展开 <tr>
并使该内容可见,并且如果该内容内存在匹配项,它将显示出来。
我尝试过的:
我使用字典将主行的 ID 映射到该行的内容数组。当搜索输入与字典中的元素匹配时,我希望显示相应的主行,即使它的内容位于当前隐藏的元素内。 但是,我似乎无法让它按预期工作。当其内容与搜索词匹配时,该行不会显示,除非手动展开。
这是我当前代码的简化版本:
@using Newtonsoft.Json
@{
// Sample machine names
var MachineNames = new List<string> { "Machine A", "Machine B", "Machine C" };
// Sample requests using anonymous objects
var requests = new[]
{
new { Id = 1, ContactName = "Client A", CompanyName = "Machine A", Status = "Pending", Msg = "Request 1" },
new { Id = 2, ContactName = "Client B", CompanyName = "Machine B", Status = "In Progress", Msg = "Request 2" },
new { Id = 3, ContactName = "Client C", CompanyName = "Machine C", Status = "Completed", Msg = "Request 3" }
};
// Sample dictionary data for matching the behavior of your original example
var requestDictionary = new Dictionary<int, string[]>
{
{ 1, new[] { "client a", "machine a", "pending", "request 1" } },
{ 2, new[] { "client b", "machine b", "in progress", "request 2" } },
{ 3, new[] { "client c", "machine c", "completed", "request 3" } }
};
}
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Collapsible Table with Custom Filter</title>
<!-- Include jQuery -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- Include DataTables CSS & JS -->
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.min.css">
<script src="https://cdn.datatables.net/1.10.5/js/jquery.dataTables.min.js"></script>
<style>
table {
width: 100%;
border-collapse: collapse;
}
th, td {
padding: 8px;
text-align: left;
border-bottom: 1px solid #ddd;
}
.show {
display: table-row;
}
.dataTables_filter label {
font-weight: bold;
font-size: 1.2em;
}
.dataTables_filter input {
margin-left: 10px;
padding: 5px;
border-radius: 5px;
border: 1px solid #ccc;
}
#search-container {
width: auto;
padding: 5px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<h1>Collapsible Table with Custom Search Filter</h1>
<!-- Search filter -->
<div id="search-container"></div>
<!-- The table with collapsible rows -->
<table id="myTable" class="display table-flexible">
<thead>
<tr>
<th>Request ID</th>
<th>Client</th>
<th>Machine</th>
<th>Status</th>
<th>Description</th>
</tr>
</thead>
<tbody>
@foreach (var request in requests)
{
<tr>
<td>@request.Id</td>
<td>@request.ContactName</td>
<td data-id="@request.CompanyName">@request.CompanyName</td>
<td>@request.Status</td>
<td>
<button class="btn btn-info btn-sm toggle-btn" data-target="#[email protected]">Details</button>
</td>
</tr>
<tr id="[email protected]" class="details-row" style="display: none;">
<td colspan="6">
<div class="card custom-card-body details-card">
<div class="detail-item">
<strong>Message:</strong>
<p class="tw-font-bold">@request.Msg</p>
</div>
</div>
</td>
</tr>
}
</tbody>
</table>
@section Scripts {
<script src="https://cdn.datatables.net/1.10.5/js/jquery.dataTables.min.js"></script>
<script>
$(document).ready(function () {
var requestDictionary = @Html.Raw(JsonConvert.SerializeObject(requestDictionary));
console.log(requestDictionary); // Debugging purposes
// Initialize DataTable
var table = $('#myTable').DataTable({
columnDefs: [{
"defaultContent": "-",
"targets": "_all"
}],
paging: false,
ordering: false,
info: false,
dom: 'ft'
});
// Move search box to custom container
$('#search-container').html($('.dataTables_filter'));
// Custom search functionality using the requestDictionary
function filterTable(searchTerm) {
var rows = table.rows().nodes(); // Fetch all rows
$(rows).each(function () {
var $row = $(this); // The `tr` element
// Extract requestId from the first column (adjust if necessary)
var requestId = $row.find('td').first().text().trim();
// Ensure requestId is a valid number
requestId = parseInt(requestId, 10);
if (isNaN(requestId)) {
return; // Skip rows without a valid requestId
}
// Check if requestId exists in the dictionary
if (!requestDictionary.hasOwnProperty(requestId)) {
return;
}
var requestDetails = requestDictionary[requestId];
console.log(requestDetails); // Debugging purposes
// Check if any of the details contain the search term
var match = requestDetails.some(function (detail) {
return detail.toLowerCase().includes(searchTerm.toLowerCase());
});
// Show or hide the row based on the search match
if (match) {
console.log("HIT - Showing row for requestId:", requestId);
$row.css("display", "table-row"); // Set display to table-row
} else {
console.log("MISS - Hiding row for requestId:", requestId);
$row.css("display", "none"); // Hide row
}
});
}
// Handle search input
$('.dataTables_filter input[type="search"]').on('input', function () {
var searchTerm = $(this).val().trim();
filterTable(searchTerm);
});
// Attach event listeners for toggling rows
$('.toggle-btn').on('click', function () {
var target = $(this).data('target');
$(target).fadeToggle(500);
});
});
</script>
}
</body>
感谢您的时间和关注!
我认为问题出在你的函数内部。 您正在做的是,找到匹配项后,您正在对当前正在循环内部处理的同一行进行操作。 相反,您需要使用当前请求 ID 查找详细信息行并显示该行。
这是您可以尝试的可能解决方案之一。
function filterTable(searchTerm) {
// First hide all the details row
$('.details-row').css('display', 'none');
var rows = table.rows().nodes(); // Fetch all rows
$(rows).each(function() {
var $row = $(this); // The `tr` element
// Extract requestId from the first column (adjust if necessary)
var requestId = $row.find('td').first().text().trim();
// Ensure requestId is a valid number
requestId = parseInt(requestId, 10);
if (isNaN(requestId)) {
return; // Skip rows without a valid requestId
}
// Check if requestId exists in the dictionary
if (!requestDictionary.hasOwnProperty(requestId)) {
return;
}
var requestDetails = requestDictionary[requestId];
// console.log(requestDetails); // Debugging purposes
// Check if any of the details contain the search term
var match = requestDetails.some(function(detail) {
return detail.toLowerCase().includes(searchTerm.toLowerCase());
});
// Show the details row based on the search match
if (match) {
$('#detailsCollapse_' + requestId).css('display', 'table-row');
}
});
}