您现在的位置:首页 >> 前端 >> 内容

如何动态的制作级联菜单(上)

时间:2017/8/4 17:00:56 点击:

  核心提示:在开发的过程中,需要制作一个级联下拉框的功能,先阐述功能详情,如图: 父选项框2根据父选项框1中的选项,进行动态加载选项详情;子选项框1根据父选项框2的选项,进行动态加载选项详情;子选项2根据子选项框...

在开发的过程中,需要制作一个级联下拉框的功能,先阐述功能详情,如图:

如何动态的制作级联菜单(上)

父选项框2根据父选项框1中的选项,进行动态加载选项详情;子选项框1根据父选项框2的选项,进行动态加载选项详情;子选项2根据子选项框1的选项,进行动态加载选项详情。点击新增可以新增子选项行,每一行子选项相互独立。点击删除按钮可以删除选中行的数据。

这一项功能看似简单,但是在实现过程中也会遇到许多小问题,其中之一就是新增行怎么保证每一行相互独立,在每次新增行的时候,子选项框1中的选项自动加载,而不是需要再一次触发父选项2的onchange()事件实现(因为一旦不能实现这一功能,会发现新增一行后,之前填入的数据都会因为再一次触发父选项框2的onchange()事件而消失)。

另外,因为本人也是新手上路,所以在js中如何获取到每一个控件的技巧并不是很熟练,在这一次的开发过程中也试过很多种方法,在此处也提供一个思路:

方法一:通过selector的id获取,这一方法的不足在于使用麻烦,增加了代码的复杂度,因为需要动态设置控件id;

方法二:通过DOM中的node获取,这一方法的不足在于不同的浏览器兼容性上会遇到麻烦,有的浏览器会将html文件中的回车键视作一个标签,所以会导致代码的混乱和可读性差的问题;

方法三:通过jquery语句中的selector来实现,因为jquery使用方法很灵活,内置函数也很多,所以就很好的满足了兼容性方面的问题,具体使用方法在后续代码中会有介绍。

具体代码展示如下:

Html代码

<thead>
<tr>
    <td>父选项1</td>
    <td>
    <select id="" class="form-control parentItem"name="parentIt    em" required="required" onchange="changeItem()" >
        <option VALUE="0">请选择父选项1</option>
        <c:forEach items="${roots}" var="root">
           <option value="${root.testingItemId}">${root.itemNam            e}</option>
        </c:forEach>
    </select>
    </td>
    <td>父选项2</td>
    <td>
    <select id="testChildItem" class="form-control" name="child    Item" required="required" onchange="getChildItem()"
    value="<c:if test="${!empty lti}">${lti.itemName}</c:if>">
        <option VALUE="0">请选择父选项2</option>
    </select>
    </td>
    <td></td><td></td>
    <td>
        <button type="button" class="btn btn-default" onclick="a        ddItem(this)">新增</button>
    </td>
</tr>
</thead>

父选项框1中的选项通过这一table布局所在form的controller函数从数据库获取,并在前端通过EL表达式进行获取。

<tbody id="testItemTbody">
<tr>
    <td>子选项1</td>
    <td>
    <select class="form-control" id="testParam0" name="testPara    m" required="required" onchange="getStandard(this)">
       <option VALUE="0">请选择子选项1</option>
    </select>
    </td>
    <td>子选项2</td>
    <td>
    <select class="form-control" name="testStandard" id="testSt    andard0" required="required">
       <option VALUE="0">请选择子选项2</option>
    </select>
    </td>
    <td>input框</td>
    <td>
    <input class="form-control" name="judgement" required="requ    ired" type="text">
    </td>
    <td>
       <button type="button" class="btn btn-default" onclick=de       leteItems(this) id="deleteBtn">删除</button>
    </td>
</tr>
</tbody>

可见在窗体打开之初,就存在一行子选项行,其他子选项行通过新增按钮的additem实现。

 

Js代码

function changeItem() {
    var id = $("select[name='parentItem']").val();
    var url ="    " + id;
    var selectItem = $("select[name='childItem']");

    $.ajax({
        url:url,
        success:function (htmlData) {
            selectItem.html(htmlData);
        }
    })
}

function getChildItem() {
    var id = $("select[name='childItem']").val();
    var url = "" + id;
    var testParam = $("select[name='testParam']");

    $.ajax({
        url:url,
        dataType:'json',
        success:function (json) {
            var param = json.paramData;
            testParam.html(param);
        }
    })
}

changeItem()函数为父选项1的onchange绑定事件,通过获取父选项框1的值得到对应选项的id,并将id传入到指定url中获取选项组,并通过json形式传回到父选项框2中进行填充。

getChildItem()和getStandard()实现方法类似于changeItem()的实现方法,不过多做介绍,其功能分别为获取初始自选项行中的子选项框1和子选项框2的选项值。

function getStandard(selector) {
    var index = selector.selectedIndex;
    var id = selector.options[index].value;
    var url = "" + id;
    var testParam = btn.parentNode.parentNode.parentNode.nextSi    bling.nextSibling.lastChild.childNodes[1].childNodes[0];

    $.ajax({
        url:url,
        dataType:'json',
        success:function (json) {
            var param = json.paramData;
            testParam.innerHTML = param;
        }
    })
}

function getStandardA(selector) {
    var index = selector.selectedIndex;
    var id = selector.options[index].value;
    var url = "" + id;
    var paramStandard = selector.parentNode.parentNode.childNod    es[3];

    $.ajax({
        url:url,
        dataType:'json',

        success:function (htmlData) {
            var paramStandardA = htmlData.paramStandardA;
            paramStandard.childNodes[0].innerHTML = paramStandar            dA;
        }
    })
}

addItem()函数实现了子选项行的增加,注意观察可发现子选项行中子选项框2获取值的方法变为了getStandardA(),并在最后调用了getChildItemA()方法,进行子选项框1的动态加载。也是凭借这样的方法,实现了子选项行的相互独立。如果新增行的绑定事件和初识行相同的话,在新增行的时候只有通过再次触发事件才会获取值,不然无法获取。

function getChildItemA(btn) {
    var id = $("select[name='childItem']").val();
    var url = "<spring:url value="/testingContract/getItemDetai    l/"/>" + id;
    var testParam = btn.parentNode.parentNode.parentNode.nextSi    bling.nextSibling.lastChild.childNodes[1].childNodes[0];

    $.ajax({
        url:url,
        dataType:'json',
        success:function (json) {
            var param = json.paramData;
            testParam.innerHTML = param;
        }
    })
}

function getStandardA(selector) {
    var index = selector.selectedIndex;
    var id = selector.options[index].value;
    var url = "<spring:url value="/testingContract/getItemStand    ard/"/>" + id;
    var paramStandard = selector.parentNode.parentNode.childNod    es[3];

    $.ajax({
        url:url,
        dataType:'json',

        success:function (htmlData) {
            var paramStandardA = htmlData.paramStandardA;
            paramStandard.childNodes[0].innerHTML = paramStandar            dA;
        }
    })
}

 

因为additem()中新增的html代码是通过string拼接而成,不存在回车等影响因素,所以可以大胆使用node进行控件的获取,当然此处完全可以使用之前的selector方法进行获取,此处仅为演示node使用方法。

function deleteItems(btn){
    var rows = document.getElementById("TestItemsTable").rows.l    ength;
    if(rows > 2){
        $(btn).parent().parent().remove();
    }else{
        alert("不能删除!");
    }
}

删除

今天的介绍就到这里,明天为大家带来将这一动态下拉框的数据合并并填入数据库的方法。

作者:网络 来源:JavaTree的博