jquery select2优化下拉多选框(二)

上篇文章实现了多选下拉框,这次的下拉框要求实现树形结构
最终效果:在这里插入图片描述

代码:
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. 问题:比如全部选中水果类的时候,选中项最好只展示水果这个大类别,如图:在这里插入图片描述

  1. 代码并不完美,如果有大佬有更好的方法,希望可以留言一下
  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值