jquery - 根据第一个选择动态填充第二个下拉菜单
问题描述
我正在使用以下代码动态填充两个下拉菜单“searchProject”和“searchHR”。用户可以从“searchProject”中选择一个值,从“searchHR”中选择多个值来过滤数据表。
我试图让第二个下拉菜单“searchHR”填充基于在第一个下拉菜单“searchProject”中选择的单个值的值。
这是我当前的代码:
var sortFunction = function (a, b) {
if (a < b) return -1;
if (a > b) return 1;
return 0;
};
$(document).ready(function () {
var ex_table = $('#data_table').DataTable({
"order": [],
pageLength: 50,
ajax: {
url: '/db',
dataSrc: "",
type: "POST",
'data': function (d) {
return $.extend({}, d, {
"project_name": $('#searchProject').val(),
"hour": $('#searchHR').val(),
});
},
"serverSide": true,
},
columns: [
{data: 'project_name'},
{data: 'id'},
{data: 'hour'},
],
"initComplete": function () {
ex_table.columns([0]).every(function () {
const column = this;
const select = $('#searchProject')
.on('change', function () {
const Project_val = $(this).val();
column.search(Project_val).draw();
});
column.data().unique().sort().each(function (d) {
select.append('<option value="' + d + '">' + d + '</option>')
});
});
ex_table.columns([2]).every(function () {
const column = this;
const select = $('#searchHR')
.on('change', function () {
var vals = $('option:selected', this).map(function (index, element) {
return $.fn.dataTable.util.escapeRegex($(element).val());
}).toArray().join('|');
column.search(vals.length > 0 ? '^(' + vals + ')$' : '', true, false).draw();
});
column.data().unique().sort(sortFunction).each(function (d) {
select.append('<option value="' + d + '">' + d + '</option>')
});
});
}
});
})
HTML:
<label for="searchProject"></label><select id="searchProject" class="js-example-basic-single" style="width: 10%">
<option></option>
</select>
<label for="searchHR"></label><select id="searchHR" class="js-example-basic-multiple" multiple="multiple" style="width:15%">
<option></option>
</select>
任何帮助将不胜感激。谢谢。
解决方案
这是一种方法——我对代码进行了注释以提供对主要步骤的解释。大多数复杂性来自 (a) 管理两个选择小部件之间的关系,以及 (b) 处理来自多选的值数组。
// inline test data:
var dataSet = [
{
"id": "123",
"name": "Tiger Nixon",
"position": "System Architect",
"salary": "$320,800",
"start_date": "2011/04/25",
"office": "Edinburgh",
"extn": "5421"
},
{
"id": "456",
"name": "Donna Snider",
"position": "Customer Support",
"salary": "$112,000",
"start_date": "2011/01/25",
"office": "New York",
"extn": "4226"
},
{
"id": "567",
"name": "Cedric Kelly",
"position": "Senior Javascript Developer",
"salary": "$433,060",
"start_date": "2012/03/29",
"office": "Edinburgh",
"extn": "6224"
},
{
"id": "432",
"name": "Airi Satou",
"position": "Accountant",
"salary": "$162,700",
"start_date": "2008/11/28",
"office": "Tokyo",
"extn": "5407"
},
{
"id": "987",
"name": "Brielle Williamson",
"position": "Integration Specialist",
"salary": "$372,000",
"start_date": "2012/12/02",
"office": "New York",
"extn": "4804"
}
];
$(document).ready(function() {
var table = $('#example').DataTable( {
data: dataSet,
orderCellsTop: true,
columns: [
{ data: "name" },
{ data: "office" },
{ data: "position" },
{ data: "extn" }
],
initComplete: function () {
this.api().columns( [1, 2] ).every( function () {
var column = this;
var colIdx = column.index();
var node;
var select;
if (colIdx === 1) {
node = $('#office_select');
select = $('<select><option value=""></option></select>');
} else {
node = $('#position_select');
select = $('<select multiple><option value=""></option></select>');
}
select.appendTo( $(node).empty() )
.on( 'change', function () {
// the contents of the multi-select, as an array of values:
var val = $(this).val();
if (colIdx === 1) { // this is the standard select column (for "office")
val = $.fn.dataTable.util.escapeRegex(val);
column.search( val ? '^' + val + '$' : '', true, false ).draw();
rebuildPositionSelect();
} else { // this is the multi-select column (for "position"):
// build a string containing the pipe-separated multiselect values, but
// with each value escaped for any regex characters it may contain:
var vals = val.map(x => $.fn.dataTable.util.escapeRegex(x)).join('|');
column.search( vals ? '^' + vals + '$' : '', true, false ).draw();
}
} );
column.data().unique().sort().each( function ( val ) {
select.append( '<option value="' + val +'">' + val + '</option>' )
} );
} );
}
} );
function rebuildPositionSelect() {
var select = $('#position_select select').empty().append('<option value=""></option>');
// note the use of {search:'applied'} here, to only capture visible "position" values:
var column = table.column(2, {search:'applied'});
// we need to reset the "position" search back to "none", to unfilter that column,
// otherwise our new filter may not find the already filtered data:
column.search('').draw();
column.data().unique().sort().each( function ( val ) {
select.append( '<option value="' + val +'">' + val + '</option>' );
} );
}
} );
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Demo</title>
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.22/css/jquery.dataTables.css">
<link rel="stylesheet" type="text/css" href="https://datatables.net/media/css/site-examples.css">
</head>
<body>
<div style="margin: 20px;">
<div>
<span>Office: </span>
<span id="office_select"></span>
<span> Position: </span>
<span id="position_select"></span>
</div>
<br><br>
<table id="example" class="display dataTable cell-border" style="width:100%">
<thead>
<tr>
<th>Name</th>
<th>Office</th>
<th>Position</th>
<th>Extn.</th>
</tr>
</thead>
</table>
</div>
</body>
</html>
一些注意事项:
用户界面可以改进!选择下拉菜单和多选没有任何样式/定位 CSS。
因为从第一个(“office”)下拉列表到第二个(“position”)多选存在依赖关系,所以每当我们对第一个下拉列表进行更改时,我们都必须清除所有多选选择。如果没有这个,您最终可能会得到与所选下拉列表无关的多选值。
代码可以(并且可能应该)重新排列成组织更好的结构。目前,我的大部分代码都只是转储到
initComplete
函数中。
(我纯粹的个人偏好是通常避免这种类型的选择依赖,因为它可能会让用户感到惊讶。)
推荐阅读
- kafka-consumer-api - 从主题中 kafka 分区的特定偏移量启动 flink 流应用程序
- c# - EWS SaveHttpResponseHeaders 异常 - 已添加具有相同密钥的项目
- python - 每 10 分钟运行一次并生成 csv 文件的 python 脚本
- javascript - 是否可以将 y 轴标签复制到谷歌图表的右侧?
- r - 自定义绘图函数错误 R - FUN 中的错误(X[[i]],...):找不到对象“物种”
- flutter - Hive .g.dart 文件未生成
- vue.js - 带有 Bootstrap 5.1.0 的 Vue.js 2.6.12 - 手动组件启动问题
- ruby - 使用 Time.parse() 而不是 DateTime.parse() 会无限延长执行时间
- azure - 如何使用 ARM 模板创建 CosmosDB SQL API 无服务器帐户?
- python - 我无法使用 python 正确循环遍历 xml 文件,如何循环并以正确的顺序返回多个不同的标签?