上篇文章实现了多选下拉框,这次的下拉框要求实现树形结构
最终效果:
代码:
html
<select id="userType" multiple style="width: 100%" data-placeholder="请选择" data-tags="true"></select>
js
//defaultData是回显时的data
function initUserType (defaultData) {
var children = []
let $select2 = $('#userType');
//ajax请求数据
$.ajax({
url: url,
type: "get",
async: false,
success: function (data) {
children = data
}
});
var data = [
{
"id": "user_type",
"text": "人员类别",
"children": children
}
];
//select2配置项
$select2.select2({
data: data,
allowClear: true, //允许清空
closeOnSelect: false, //选中后是否关闭选择框,默认为true
width: '100%',
language: {
noResults: function (param) {
return "暂无数据"
}
},
templateResult: formatResult
})
//select2数据回调函数,给下拉项添加复选框
function formatResult(state) {
if (Select2MultiCheckBoxObj.length > 0) {
var stateId = staticWordInID + state.id;
for (let i = 0; i < Select2MultiCheckBoxObj.length; i++) {
const element = Select2MultiCheckBoxObj[i];
if (element.id === state.id) {
var checkbox = $('<div class="checkbox"><input class="select2Checkbox" id="' + stateId + '" type="checkbox" ' + (Select2MultiCheckBoxObj[i]["IsChecked"] ? 'checked' : '') +
'><label for="checkbox' + stateId + '">' + state.text + '</label></div>', { id: stateId });
return checkbox;
}
if (element.children && element.children.length > 0) {
const childIndex = findIndexRecursive(element.children, state.id, 0);
if (childIndex !== -1) {
var checkbox = $('<div class="checkbox"><input class="select2Checkbox" id="' + stateId + '" type="checkbox" ' + (Select2MultiCheckBoxObj[i].children[childIndex]["IsChecked"] ? 'checked' : '') +
'><label for="checkbox' + stateId + '">' + state.text + '</label></div>', { id: stateId });
return checkbox;
}
}
}
}
}
// 等待Select2渲染完成后设置默认选中项
$select2.on('select2:open', function () {
var defaultValues = []; // 这里是人员类别下的所有子项的id列表
//如果有回显数据,显示回显数据
if (defaultData){
// defaultValues.push('1', '5', '6', '7', '8', 'B5')
for (let i=0; i<defaultData.length; i++){
defaultValues.push(defaultData[i].relationalUserType);
$("state_" + defaultData[i].relationalUserType).prop("checked",true);
let childIndex = Select2MultiCheckBoxObj[0].children.findIndex(x => x.id == defaultData[i].relationalUserType);
if (childIndex > -1){
Select2MultiCheckBoxObj[0].children[childIndex]['IsChecked'] = true;
}
}
}else{//如果没有默认选中全部
// 当Select2打开时,说明它已经初始化完成
// 你可以在这里安全地设置默认值
for (let i=0; i<data[0].children.length; i++){
defaultValues.push(data[0].children[i].id)
$("state_" + data[0].id).prop("checked",true);
Select2MultiCheckBoxObj[0]['IsChecked'] = true;
$("state_" + data[0].children[i].id).prop("checked",true);
for (let j=0; j<Select2MultiCheckBoxObj[0].children.length; j++){
Select2MultiCheckBoxObj[0].children[j]['IsChecked'] = true;
}
}
}
$select2.val(defaultValues).trigger("change");
// 由于我们只想设置一次默认值,所以在设置后立即解绑这个事件
$select2.off('select2:open');
});
$.map($('#' + id_selectElement + ' optgroup'), function (option,index) {
AddItemInSelect2MultiCheckBoxObj(option, false);
});
//点击复选框触发事件
$(document).on("click", ".select2Checkbox", function (event) {
debugger;
let selector = "#" + this.id;
// let isChecked = Select2MultiCheckBoxObj[Select2MultiCheckBoxObj.
// findIndex(x => x.id == this.id.replaceAll(staticWordInID, ''))]['IsChecked'];
let checked2 = false;
let thisId = this.id;
let modifiedId = thisId.replaceAll(staticWordInID, '');
let index = Select2MultiCheckBoxObj.findIndex(x => x.id == modifiedId); // 在数组中找到与修改后的ID匹配的元素的索引
for (let i = 0; i < Select2MultiCheckBoxObj.length; i++) {
const element = Select2MultiCheckBoxObj[i];
if (index > -1 && ("state_" + element.id) == thisId) {
let matchingElement = Select2MultiCheckBoxObj[index]; // 使用索引获取匹配的数组元素
isChecked2 = matchingElement.IsChecked ? false : true;
// isChecked2 = matchingElement.IsChecked;
Select2MultiCheckBoxObj[index]["IsChecked"] = isChecked2;
AddItemInSelect2MultiCheckBoxObj(Select2MultiCheckBoxObj[index], isChecked2);
$.each(element.children, function (childrenIndex, childObj) {
childObj.IsChecked = isChecked2;
AddItemInSelect2MultiCheckBoxObj(Select2MultiCheckBoxObj[index].children[childrenIndex], isChecked2);
Select2MultiCheckBoxObj[i].children[childrenIndex]["IsChecked"] = isChecked2
$("#" + staticWordInID + childObj.id).prop("checked", isChecked2);
});
selectAll(modifiedId);
}
if (index == -1) {
if (element.children && element.children.length > 0) {
// const childIndex = findIndexRecursive(element.children, modifiedId, 0);
let childIndex = element.children.findIndex(x => x.id == modifiedId); // 在数组中找到与修改后的ID匹配的元素的索引
if (childIndex > -1) {
let matchingElement = element.children[childIndex]; // 使用索引获取匹配的数组元素
// isChecked2 = matchingElement.IsChecked ? false : true;
isChecked2 = matchingElement.IsChecked;
// Select2MultiCheckBoxObj[i].children[childIndex]["IsChecked"] = isChecked2;
$(selector).prop("checked", isChecked2);
}
}
}
}
});
//选中某一项时触发
$select2.on("select2:select", function (event) {
$("#" + staticWordInID + event.params.data.id).prop("checked", true);
AddItemInSelect2MultiCheckBoxObj(event.params.data, true);
//If all options are slected then selectAll option would be also selected.
if (Select2MultiCheckBoxObj.filter(x => x.IsChecked === false).length === 1) {
AddItemInSelect2MultiCheckBoxObj(0, true);
$("#" + staticWordInID + "0").prop("checked", true);
}
});
//删除某一项时触发
$select2.on("select2:unselect", function (event) {
$("#" + staticWordInID + "0").prop("checked", false);
AddItemInSelect2MultiCheckBoxObj(0, false);
$("#" + staticWordInID + event.params.data.id).prop("checked", false);
AddItemInSelect2MultiCheckBoxObj(event.params.data, false);
});
//输入框中值改变触发
$(document).on("change", "#userType", function (e) {
var checkedList = $("#userType option:selected");//获取选中项
if (checkedList.length > 1) {
$.each(checkedList, function (i, item) {
var uldiv = $("#userType").siblings('span.select2').find('ul');
var li0 = uldiv.find("li").eq(0);
var li1 = uldiv.find("li").eq(1);
//dom元素只能使用原生js进行赋值checkList[0].text √ checkList[0].text() ×
li0.html('<span class="select2-selection__choice__remove" role="presentation">×</span>' + checkedList[0].text)
li1.text("+" + (checkedList.length - 1))
li1.nextAll().remove();
})
}
})
}
function AddItemInSelect2MultiCheckBoxObj(optionData, IsChecked) {
var children = optionData.children;
var id = "";
if (optionData.value) {
id = optionData.value;
} else {
id = optionData.id;
}
var len = Select2MultiCheckBoxObj.length;
if (children) {
if (Select2MultiCheckBoxObj.length > 0) {
let index = Select2MultiCheckBoxObj.findIndex(x => x.id == id);
if (index > -1) {
Select2MultiCheckBoxObj[index]["IsChecked"] = IsChecked;
}
else {
if (children.length > 0) {
Select2MultiCheckBoxObj.push({ "id": id, "IsChecked": IsChecked, "children": [] });
for (let i = 0; i < children.length; i++) {
Select2MultiCheckBoxObj[len].children.push({ "id": children[i].value, "IsChecked": IsChecked })
}
}
}
} else {
Select2MultiCheckBoxObj.push({ "id": id, "IsChecked": IsChecked, "children": [] });
if (children.length > 0) {
for (let i = 0; i < children.length; i++) {
Select2MultiCheckBoxObj[0].children.push({ "id": children[i].value, "IsChecked": IsChecked })
}
}
}
} else {
for (let i = 0; i < len; i++) {
let element = Select2MultiCheckBoxObj[i];
$.each(element.children, function (childrenIndex, childObj) {
if (id == childObj.id) {
Select2MultiCheckBoxObj[i].children[childrenIndex]['IsChecked'] = IsChecked
Select2MultiCheckBoxObj[i]['IsChecked'] = IsChecked
}
});
var allFalse = true;
$.each(element.children, function (index, value) {
// 如果发现任何一个值不为 false,设置 allFalse 为 false 并停止遍历
if (value.IsChecked !== false) {
allFalse = false;
return false; // 相当于每个循环中的 break
}
});
// 如果遍历完成且 allFalse 仍为 true,说明所有值都为 false
if (allFalse) {
// 数组中的所有值都为 false,执行的代码
Select2MultiCheckBoxObj[i]['IsChecked'] = false;
}
}
}
}
function findIndexRecursive(array, id, currentIndex = 0) {
for (let i = currentIndex; i < array.length; i++) {
const element = array[i];
if (element.id === id) {
return i; // 如果找到了匹配的id,返回当前索引
}
if (element.children && element.children.length > 0) {
const childIndex = findIndexRecursive(element.children, id, 0);
if (childIndex !== -1) {
return i; // 如果在子数组中找到匹配的id,返回外层数组的索引
}
}
}
return -1; // 如果没有找到匹配的id,返回-1
}
注意:1. 打开页面时可使用KaTeX parse error: Expected 'EOF', got '#' at position 3: ("#̲userType").sele…(“#userType”).empty();再调用initUserType()
3. 初始化后选中默认值后不点击下拉框的话就不会触发输入框的change方法,不会显示选中项,可以使用 $select2.select2(‘open’);打开下拉项再执行 $select2.select2(‘close’);关闭下拉项,这样在视觉上可以呈现初始化展示选中项的效果。
4. 问题:比如全部选中水果类的时候,选中项最好只展示水果这个大类别,如图:
- 代码并不完美,如果有大佬有更好的方法,希望可以留言一下