如何用bootstrapDualListbox()实现同一选项的多次重复选择?
实现支持重复选择的双列表组件(替代bootstrapDualListbox)
首先明确:bootstrapDualListbox 基于原生 <select multiple> 实现,而原生select的机制决定了每个 <option> 只能被选中一次,无法直接满足重复选择同一值的需求。要实现选中如1,1,2,3,3这类重复项的效果,需要自定义逻辑,下面提供一种可行的替代方案:
方案思路
放弃依赖原生select的选中机制,改为手动维护右侧已选列表的DOM元素:每次选择左侧选项时,复制一个相同的选项到右侧列表(而非移动原选项),以此支持重复添加同一值。
完整代码实现
HTML结构
<div class="row"> <div class="col-md-5"> <h5>可选列表</h5> <select id="availableSelect" multiple class="form-control" size="5"> <option value="1"> One </option> <option value="2"> Two</option> <option value="3"> Three</option> </select> <button id="addBtn" class="btn btn-primary mt-2">→ 添加</button> </div> <div class="col-md-2 d-flex align-items-center justify-content-center"> <!-- 占位列 --> </div> <div class="col-md-5"> <h5>已选列表</h5> <div id="selectedContainer" class="border rounded p-2" style="min-height: 120px; overflow-y: auto;"> <!-- 动态生成已选项 --> </div> <button id="removeBtn" class="btn btn-danger mt-2">← 移除选中</button> </div> </div>
JavaScript逻辑
// 添加选项到已选列表 document.getElementById('addBtn').addEventListener('click', function() { const availableSelect = document.getElementById('availableSelect'); const selectedContainer = document.getElementById('selectedContainer'); // 获取左侧选中的所有选项 const selectedOpts = Array.from(availableSelect.selectedOptions); selectedOpts.forEach(opt => { // 复制原选项作为已选项节点 const clonedOpt = opt.cloneNode(true); clonedOpt.classList.add('selected-item'); // 给已选项添加点击选中样式 clonedOpt.style.display = 'block'; clonedOpt.style.padding = '4px 8px'; clonedOpt.style.cursor = 'pointer'; clonedOpt.addEventListener('click', function() { this.classList.toggle('bg-primary'); this.classList.toggle('text-white'); }); // 添加到右侧容器 selectedContainer.appendChild(clonedOpt); }); // 清空左侧选中状态 availableSelect.selectedIndex = -1; }); // 移除选中的已选项 document.getElementById('removeBtn').addEventListener('click', function() { const selectedContainer = document.getElementById('selectedContainer'); const itemsToRemove = selectedContainer.querySelectorAll('.selected-item.bg-primary'); itemsToRemove.forEach(item => selectedContainer.removeChild(item)); }); // 获取所有已选值(提交表单时调用) function getSelectedValues() { const selectedItems = document.querySelectorAll('#selectedContainer .selected-item'); return Array.from(selectedItems).map(item => item.value); }
可选样式优化
.selected-item:hover { background-color: #f0f0f0; } .selected-item.bg-primary { background-color: #0d6efd !important; }
方案说明
- 左侧保留原生select用于选择选项,但不依赖它的选中状态维护已选列表
- 点击添加按钮时,复制选中的选项到右侧容器,同一选项可被多次添加
- 右侧已选项支持点击选中,再通过移除按钮删除选中的项
- 最终可通过
getSelectedValues()方法获取包含重复项的所有已选值
如果一定要基于bootstrapDualListbox改造,需要修改插件核心逻辑:将选项移动操作改为复制操作,但这种方式需要深入修改插件源码,维护成本较高,不如自定义实现灵活。
内容的提问来源于stack exchange,提问作者ihavenokia
相关产品推荐
相关产品推荐

