目录
一、问题描述
工作中遇到的需求,需要将下拉单选框改成下拉多选框,因此使用Bootstrap-select插件完成。这个下拉单选框可以通过按钮切换为输入框,选中项或输入项都添加为radio单选按钮。过程中遇到了以下问题。
- Bootstrap-select显示出错,总是显示两个下拉多选框
- Bootstrap-select宽度width问题
- radio单选按钮组去重
二、具体实现
1. 下载Bootstrap-select及汉化插件并引入
- Bootstrap-select中文网:https://www.bootstrapselect.cn/
- Github地址: https://github.com/silviomoreto/bootstrap-select
引入:
<link href="static/bootstrap4/css/bootstrap.css" rel="stylesheet" type="text/css">
<link href="static/bootstrap4/css/bootstrap-select.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="static/bootstrap4/js/bootstrap.min.js"></script>
<script type="text/javascript" src="static/bootstrap4/js/bootstrap-select.min.js"></script>
<script type="text/javascript" src="static/bootstrap4/js/defaults-zh_CN.js"></script>
2. bootstrap-select下拉多选实现
HTML
主要是在select标签加上class="selectpicker"
和multiple
。
<div class="row" id="answer_part_div">
<div class="col-sm-10" id="answer_select_div">
<label for="answer_select"></label>
<select class="selectpicker" multiple required id="answer_select">
<option value="" hidden>请选择候选项</option>
</select>
</div>
<div class="col-sm-10" id="answer_input_div" style="display: none">
<input type="text" name="answer" class="form-control" placeholder="请输入候选项" required>
</div>
<div class="col-sm-2 m-auto">
<button class="btn btn-sm btn-primary" id="answer_toggle_btn" title="切换输入">
<i class="fas fa-keyboard"></i>
</button>
<button class="btn btn-sm btn-success" id="answer_confirm_btn" title="确认添加">
<i class="fas fa-check"></i>
</button>
<button class="btn btn-sm btn-danger" title="删除选项" id="answer_del_btn">
<i class="fas fa-minus"></i>
</button>
</div>
</div>
<div id="answer_list_div" class="col-sm-12 mt-5"></div>
JS
- 解决显示出两个多选框的问题
由于这里是一个类似问卷出题的系统,每个问题+选项div是一个模板,出题者每次点击添加问题按钮,就会复制一份这个div模板。可能是复制的时候使用bootstrap-select这个插件有问题,就会在answer_select_div这个div下显示出两个bootstrap-select下拉框。解决方法是在每次添加问题之后先清除answer_select_div的内容,然后再次添加这个下拉多选框。(也就是之前在HTML文件写的answer_select_div内的内容是无效的,直接在JS插入了这个HTML内容)
// 这里使用了bootstrap-select,显示上稍微有点问题,需要先清空answer_select_div,再插入answer_select
var answer_select_div = $("#answer_select_div");
answer_select_div.empty();
// 插入answer_select
var answer_select = $("<select class='selectpicker' multiple required id='answer_select' data-width='100%'></select>");
answer_select_div.append(answer_select);
// 获取answer_select
var select = $(".selectpicker");
// 插入选项,这里是一个示例
select.append("<option value='' hidden>请选择候选项</option>");
//使用refresh方法更新UI以匹配新状态。
select.selectpicker('refresh');
//render方法强制重新渲染引导程序 - 选择ui。
select.selectpicker('render');
注意一定要调用select.selectpicker(‘refresh’)和select.selectpicker(‘render’),否则将UI无法更新。
- 解决该下拉复选框的宽度width问题
问题:在css中设置如下内容,在选中项过多时,会造成布局溢出。
/*调整下拉复选框的宽度*/
.bootstrap-select:not([class*="col-"]):not([class*="form-control"]):not(.input-group-btn) {
width: 100%;
}
解决:查阅bootstrap-select的文档,使用data-width属性来定义宽度,可选的值有以下4个。
- auto:select的宽度由option中内容宽度最宽的哪个决定;
- fit:select的宽度由实际选中的option的宽度决定;
- 100px:select的宽度定义为100px;
- 50%:select的宽度设置为父容器宽度的50%。
- 选中项或输入框输入项插入为radio单选按钮组
$(document).on("click", "#answer_confirm_btn", function () {
var cur_div = $(this).parents("#a_div");
var err_msg = "";
var unique_id = cur_div.parents(".qa_div").attr("id");
// 判断输入框是否可见
var input_visible = cur_div.find("#answer_input_div").is(":visible");
// 插入输入的选项
if (input_visible) {
// 获取输入的内容
var input_val = cur_div.find("input[name='answer']").val();
// 输入内容判断
if (input_val === "") {
err_msg = "选项内容不能为空";
}
$.each(cur_div.find("#answer_list_div label"), function (i, obj) {
if (input_val === obj.textContent) {
err_msg = "选项已存在";
}
});
if (err_msg) {
show_toast(err_msg);
// 清空候选项内容
cur_div.find("input[name='answer']").val("");
return;
}
// 插入选项
insertRadio(cur_div, unique_id, input_val);
// 清空已提交的候选项内容
cur_div.find("input[name='answer']").val("");
}
// 改变多选的选项
else {
// 获取多选数组
var select_val = cur_div.find("#answer_select").val();
// 删除数组中第一个空值
if (select_val.length && select_val[0] === "") {
select_val.shift();
}
// 选项内容判断
if (select_val.length === 0) {
err_msg = "选项内容不能为空";
}
if (err_msg) {
show_toast(err_msg);
return;
}
// 遍历数组,插入选项
select_val.forEach(function (val) {
insertRadio(cur_div, unique_id, val);
});
}
});
// 插入选项
function insertRadio(cur_div, unique_id, val) {
// 去重
var isExisted = false;
var answer_list = cur_div.find(".custom-radio input");
// 遍历radio
if(answer_list) {
$.each(answer_list, function (i, answer) {
if(answer && $(answer).val() === val) {
isExisted = true;
}
})
}
// 如果已经存在,就不插入了
if(!isExisted) {
// 新建radio
var radio_id = unique_id + "_" + val;
var new_radio = $("<div class='custom-control custom-radio'>" + "<input type='radio' id='" + radio_id + "' value='" + val + "' name='" + unique_id + "' class='custom-control-input'>" + "<label class='custom-control-label' for='" + radio_id + "'>" + val + "</label>" + "</div>");
cur_div.find("#answer_list_div").append(new_radio);
}
}
本来实现的效果是:每次改变多选选项,清空answer_list_div,重新插入多选的选项,即cur_div.find("#answer_list_div").empty();
再插入选项。但这样会导致在input框手动输入的radio选项丢失,因此还是采用了在insertRadio方法中判断是否重复后插入选项的方法。
三、参考博客
bootstrap-select 的多选+模糊查询下拉框详解(官方示例文档解读)
BootStrap-select插件动态添加option无法显示