实现多Part中多选分类选项的互斥禁用功能
解决方案
核心实现逻辑
- 用对象跟踪已选中的分类,记录每个分类被哪个Part选中
- 监听多选框的变化事件,实时更新选中状态
- 遍历所有Part的分类选项,根据选中状态同步设置禁用/启用,并刷新插件使状态生效
修改后的完整代码
<body> <div class="modal-body flex flex-col"> <div> <label for="part_input">How many part do you want?</label> <input class="rounded-md mx-3" type="number" name="input" id="input" min="1" max="10" style="height: 30px;width: 100px" placeholder="e.g. 1" required> <button type="submit" id="generateFields" class="bg-blue-500 rounded" style="width: 80px; height: 30px;">Enter</button> </div> <form method="POST" action=""> <div id="partContainer"></div> <div class="float-right mt-4" id="buttons" style="display: none"> <button type="button" class="bg-blue-400 rounded hover:bg-blue-300" style="width: 100px">Create</button> <button data-dismiss="modal" class="border bg-white rounded hover:bg-gray-100" style="width: 100px; margin-left:10px">Cancel</button> </div> </form> </div> </body> <script> document.addEventListener("DOMContentLoaded", function() { const generateButton = document.getElementById("generateFields"); const partContainer = document.getElementById("partContainer"); const buttonsDiv = document.getElementById('buttons'); // 存储已选中的分类:key为分类文本,value为选中它的Part编号 const selectedCategories = {}; // 更新所有Part的选项禁用状态 function updateCategoryDisabledStates() { document.querySelectorAll('.categorySelect').forEach(select => { const partNumber = select.id.replace('category_id', ''); select.querySelectorAll('option').forEach(option => { const categoryText = option.textContent.trim(); // 若该分类被其他Part选中,禁用当前选项 if (selectedCategories[categoryText] && selectedCategories[categoryText] !== partNumber) { option.disabled = true; } else { option.disabled = false; } }); // 刷新插件,让禁用状态生效 $(select).filterMultiSelect('refresh'); }); } generateButton.addEventListener("click", function() { const numberOfParts = parseInt(document.getElementById('input').value); if (numberOfParts >= 1 && numberOfParts <= 10) { partContainer.innerHTML = ""; // 清空上一轮的选中记录 Object.keys(selectedCategories).forEach(key => delete selectedCategories[key]); for (let i = 1; i <= numberOfParts; i++) { const partDiv = document.createElement("div"); partDiv.innerHTML = ` <h4 style="font-size:20px; margin-top:25px"><b>Part ${i}</b></h4> <div class="flex items-center"> <label for="partName${i}" class="w-32 pr-2 mt-4">Name</label> <input class="rounded-md" type="text" name="part_name${i}" id="part_name${i}" placeholder="Name" style="height: 30px; margin:15px 0px 0px 20px;width:175px;" required> </div> <div class="flex items-center"> <label for="partAmount${i}" class="w-32 pr-2 mt-4">Amount</label> <input class="rounded-md" type="number" step="0.01" name="allocation_amount${i}" id="allocation_amount${i}" placeholder="0.00" style="height: 30px; margin:15px 0px 0px 20px;text-align:right;width:175px;" required> </div> <div class="flex"> <label for="partCategory${i}" class="w-32 pr-2 mt-4">Category</label> <select class="rounded-md categorySelect" name="category_id${i}" id="category_id${i}" multiple required> <option name="category_id${i}[]" value="1" data-part="${i}"> Food & drink </option> <option name="category_id${i}[]" value="2" data-part="${i}"> Shopping </option> <option name="category_id${i}[]" value="3" data-part="${i}"> Income </option> <option name="category_id${i}[]" value="4" data-part="${i}"> Travel </option> <option name="category_id${i}[]" value="5" data-part="${i}"> Housing </option> </select> </div> `; partContainer.appendChild(partDiv); // 初始化filterMultiSelect插件 const $select = $('#category_id' + i).filterMultiSelect({ placeholderText: "Please select", }); // 监听选项变化事件 $select.on('change', function() { const partNumber = $(this).attr('id').replace('category_id', ''); // 获取当前选中的所有分类文本 const selectedTexts = $(this).find('option:selected').map(function() { return $(this).text().trim(); }).get(); // 移除当前Part之前的选中记录 Object.keys(selectedCategories).forEach(key => { if (selectedCategories[key] === partNumber) { delete selectedCategories[key]; } }); // 添加当前选中的分类记录 selectedTexts.forEach(text => { selectedCategories[text] = partNumber; }); // 更新所有Part的选项状态 updateCategoryDisabledStates(); }); } buttonsDiv.style.display = "block"; } }); }); </script>
关键修改说明
- 选中状态管理:新增
selectedCategories对象,确保同一分类只能被一个Part占用。 - 状态同步函数:
updateCategoryDisabledStates遍历所有选项,根据选中记录设置禁用状态,并调用插件的refresh方法更新UI。 - 事件监听:为每个多选框添加
change事件,实时更新选中记录并触发状态同步。 - 选项值修正:将原代码中重复的选项值改为唯一标识(实际场景中替换为真实分类ID即可)。
内容的提问来源于stack exchange,提问作者user16045271
相关产品推荐
相关产品推荐

