求助:实现模态框中序列号的跨选择器互斥显示功能
问题描述
开发了一个包含芯片(chip)和序列号(serial code)的模态框(modal),选择芯片时可切换对应的序列号,但需要实现核心功能:已被某个选择器(select)选中的序列号,不再在其他选择器中显示,目前无法完成该功能,求解决。
现有代码
JavaScript 代码
var chipsSelecionados = []; $("input[name='inventarios[]']").each(function() { var id = $(this).val(); chipsSelecionados.push(id); }); var optionsChips = seriais.map(function(seriais) { //se o selecionado var id = seriais.id; if ($.inArray(id.toString(), chipsSelecionados) === -1) { return "<option value='" + seriais.id + "'>" + seriais.serial + "</option>"; } }).join(""); $('#modal-buscar-linha').modal("hide"); var novaLinha = "<tr>" + "<input type='hidden' name='inventarios[]' value='" + idChip + "'>" + "<td style='vertical-align: middle;'><select class='form-control' style='margin: 0 auto;'>" + optionsChips + "</select></td>" + "<td>" + agenda + "</td>" + "<td style='vertical-align: middle;'><select class='form-control' style='margin: 0 auto;'><option>Não selecionar</option>" + options + "</select></td>" + "<td class='text-center'>" + "<button class='btn btn-danger delete-button' type='button'><i class='fa fa-trash' aria-hidden='true'></i></button>" + "</td>" + "</tr>";
HTML 依赖
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
解决方案
要实现目标功能,需要实时维护已选序列号集合,并在选择变化时同步更新所有下拉框选项,具体实现步骤如下:
- 维护全局已选序列号集合:用
Set存储已选ID,避免重复,提升增删和存在性检查的效率。 - 监听所有select的change事件:当选择或取消选择时,更新已选集合,并重新渲染所有select的选项。
- 封装选项渲染函数:根据当前已选集合,过滤出可选的序列号,生成对应的option元素,同时保留当前select自身的已选值。
- 处理删除行的情况:删除行时,将该行select选中的序列号从已选集合中移除,并更新其他select的选项。
优化后的JavaScript代码
// 全局存储已选的序列号ID,用Set避免重复 var selectedSerialIds = new Set(); // 初始化:从已存在的行中读取已选序列号 $("tr").find("select:first").each(function() { var selectedId = $(this).val(); if (selectedId) { selectedSerialIds.add(selectedId); } }); // 封装渲染select选项的函数 function renderSerialOptions(selectElement, currentSelectedId) { var optionsHtml = seriais.map(function(serial) { // 排除已选的(除了当前select自己选中的) if (!selectedSerialIds.has(serial.id.toString()) || serial.id.toString() === currentSelectedId) { var isSelected = serial.id.toString() === currentSelectedId ? "selected" : ""; return `<option value='${serial.id}' ${isSelected}>${serial.serial}</option>`; } }).filter(Boolean).join(""); // 过滤掉undefined项 $(selectElement).html(optionsHtml); } // 监听所有select的change事件 $(document).on("change", "tr select:first", function() { var prevId = $(this).data("prev-selected"); var newId = $(this).val(); // 移除之前选中的ID(如果存在) if (prevId) { selectedSerialIds.delete(prevId); } // 添加新选中的ID(如果不是空) if (newId) { selectedSerialIds.add(newId); } // 更新当前select的prev-selected数据 $(this).data("prev-selected", newId); // 重新渲染所有select的选项 $("tr select:first").each(function() { renderSerialOptions(this, $(this).val()); }); }); // 处理添加新行的逻辑(修改原有的novaLinha生成代码) function addNewRow(idChip, agenda) { // 初始化新select的选项:排除已选的 var optionsChips = seriais.map(function(serial) { if (!selectedSerialIds.has(serial.id.toString())) { return `<option value='${serial.id}'>${serial.serial}</option>`; } }).filter(Boolean).join(""); var novaLinha = `<tr>` + `<input type='hidden' name='inventarios[]' value='${idChip}'>` + `<td style='vertical-align: middle;'><select class='form-control' style='margin: 0 auto;'>${optionsChips}</select></td>` + `<td>${agenda}</td>` + `<td style='vertical-align: middle;'><select class='form-control' style='margin: 0 auto;'><option>Não selecionar</option>${options}</select></td>` + `<td class='text-center'>` + `<button class='btn btn-danger delete-button' type='button'><i class='fa fa-trash' aria-hidden='true'></i></button>` + `</td>` + `</tr>`; // 插入新行到表格(需替换为你的表格tbody选择器) $("#table-body").append(novaLinha); // 隐藏模态框 $('#modal-buscar-linha').modal("hide"); } // 处理删除行的逻辑 $(document).on("click", ".delete-button", function() { var row = $(this).closest("tr"); var select = row.find("select:first"); var selectedId = select.val(); // 从已选集合中移除该ID if (selectedId) { selectedSerialIds.delete(selectedId); } // 删除行 row.remove(); // 重新渲染剩余select的选项 $("tr select:first").each(function() { renderSerialOptions(this, $(this).val()); }); });
关键说明
- 使用
Set替代数组存储已选ID,避免重复值,同时增删和存在性检查的效率更高。 - 每次select选择变化时,实时更新已选集合并重新渲染所有下拉框,确保已选序列号不会出现在其他下拉框中。
- 删除行时同步移除对应已选ID,避免残留无效的已选记录。
- 渲染选项时保留当前select自身的已选值,防止当前下拉框丢失选中状态。
内容的提问来源于stack exchange,提问作者Bernardo Mantoan Castellani
相关产品推荐
相关产品推荐

