使用原生js动态生成Select,根据前面的Select的option生成二级Select

这篇博客介绍如何使用原生JavaScript动态创建二级甚至多级Select,并根据上一级Select选项来决定下级Select的生成。作者通过监听onChange事件,发送请求获取后台数据,并在接收到数据后判断是否创建新的Select。文章强调了代码的可读性和原生JS的使用,适合那些寻找不依赖库的级联Select解决方案的读者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用原生JS动态生成Select,根据前面的Select的option生成二级Select

需求描述:

  1. 后台数据会把第一层的Select的option数据 传递给前台页面,页面根据数据的有无创建第一个Select
  2. 如果后台有数据,则根据第一个Select选中的option 下面是否有数据 生成第二个Select。当点击第一个个Select的option的时候会想后台发送数据请求,后台根据数据库的返回给前台。
  3. 点击第二个Select的option的逻辑和点击第一个Select是一样的
  4. 如果存在3个select,点击第一级的select中的某一个option,如果该option没有请求到数据,则第二个和第三个select会消失

    代码步骤

    在请求这个页面的时候就会查询出数据返回给当前的页面,页面是使用vm模版的,以下是使用的标签

   <div class="col-xs-4">
                            <select id="rootId" onchange="getTypData()">
                                <option>
                                    ==请选择类型==
                                </option>
                                #foreach ($root in $!{roots})
                                    <option id="${root.route}" name="${root.name}" value="$!{root.route}">
                                        $!{root.name}
                                    </option>
                                #end
                            </select>
    </div>
   </select>

监听Select的onChange事件,实现getTypeData()

function getTypData(route) {
        var params = {};
        if (typeof(route) == "undefined" || route.length == 0) {
            var objS = document.getElementById("rootId");
            var index = objS.selectedIndex;
            if (index == 0) {
                params.isNull = true;
                params.route = objS.options[objS.selectedIndex + 1].id;
            } else {
                params.route = objS.options[objS.selectedIndex].id;
            }


        } else {
            params.route = route;
        }


        var url = "/doceditor/nextParentType";
        jQuery.ajax({
            url: url,
            type: "POST",
            cache: false,
            async: true,
            dataType: "json",
            data: params,
            success: function (data) {
                if (data != null && data.ok) {

                    var types = data.context.types;
                    var level = data.context.level;
                    createSelect(types, level);

                }
            }, ajaxError: function () {
                bapBase.alert("文本类型", "接口调用失败!");
            },
            complete: function () {
                hideWaiting();
                query();
            },
            beforeSend: function () {
                showWaiting();
            }
        });
    }

因为第一个option是 “ ==请选择类型==”所以不会携带参数过来,所以后台就会认定此前请求是第几层的第一个元素,此方法的作用就是为了点击option发送请求然后获取后台数据。判断是否生成下一个select。

在接收到数据之后就要考虑是否创建下一个select。实现createSelect()方法

function createSelect(types, level) {
        //level 作为class的标记
        if (types !== null && types !== undefined && types !== '' && types.length > 2) {

            //获取父控件div
            var divParentContext = document.getElementById("divContext");
            //获取所有的子节点
            var allDivChild = divParentContext.childNodes;

            //获取当前div所在的下标
            var index;


            if (level != null && level.length > 0) {
                //获取到当前的index
                index = level;
            } else {
                //定义div,非创建的
                index = 0;
            }
            //删除当前div以后的 div
            for (var i = allDivChild.length, len = index; i > len; i--) {
                divParentContext.removeChild(allDivChild[i - 1]);
            }

            //创建包裹select的div
            var divChidContext = document.createElement("div");

            var claz = "";
            //拼接class的值
            for (var i = 0; i < level; i++) {
                claz = i;
            }

            divChidContext.setAttribute("class", claz);
            //创建Select控件
            var mySelect = document.createElement("select");

            mySelect.setAttribute("class", claz);

            //子div添加select
            divChidContext.appendChild(mySelect);

            //父div 添加子节点div
            divParentContext.appendChild(divChidContext);

            var type = JSON.parse(types);
            var firstChild = new Option(" ==请选择类型==", "");
            mySelect.options.add(firstChild);
            for (var i in type) {
                //创建slect的option
                var optionChild = new Option(type[i].name, type[i].route);
                mySelect.options.add(optionChild);
            }
            mySelect.addEventListener("change", function () {//onchange改为change
                var index = this.selectedIndex; // 选中索引
                var route = this.options[index].value; // 选中值
                getTypData(route);
            }, false);


        } else if (types.length == 2) {
            //获取父控件div
            var divParentContext = document.getElementById("divContext");
            //获取所有的子节点
            var allDivChild = divParentContext.childNodes;
            //获取当前div所在的下标
            var index;
            if (level != null && level.length > 0) {
                //切割最后一个获取到当前的index
                index = level;
            } else {
                //定义div,非创建的
                index = 0;
            }
            //删除当前div以后的 div
            for (var i = allDivChild.length, len = index; i > len; i--) {
                divParentContext.removeChild(allDivChild[i - 1]);
            }
        }


    }

逻辑很简单,就是判断type的有无,type是后台处理此次请求返回的数据,如果没有数据和有数据的两种处理方式。
1.有数据,就开始创建Select,创建逻辑也很简单,一层一层的创建,获取父div,在获取父div下所有的div,然后删除当前div以后的所有的div,然后在创建新的div,在div 里面创建select,在select里面填充携带的数据创建option.唯一特别的一点就是这个clazz,这个clazz,就是为了和type挂钩,能够清楚简单的获取到当前所处的div的位置,从而删除当前div以后的所有div。这个程序的唯一点就是这里。这个标识在后台已经定义好了,比如说,第一层的select的第一个option的clazz 就是1或者2或者3。点击第一个option请求数据,假如有数据则第二个select的clazz就是1-4,一次类推
这里写图片描述

不这样也可以,随便你只要每次请求有动态生成而且你知道的clazz就可以了

2.没有数据就认定这个是 “ ==请选择类型==”那就删除以后的div就可以了

本来没想写这个博客的,我自己的JS不是很熟练,而且也可以看出来,我不擅长使用JQury。之所以写是因为这个需求,因为网上基本上不是啥级联表什么的,就是使用ztree什么库就可以搞定的,如果你要是遇见我这样的需求,直接拿过去用,思路很简单,而且代码都是原生的js,不怕你看不懂
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值