在开发的过程中,需要制作一个级联下拉框的功能,先阐述功能详情,如图:
父选项框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 ="<spring:url value="/testingContract/getChild/" /> " + 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 = "<spring:url value="/testingContract/getItemDetai l/"/>" + 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 = "<spring:urlvalue="/testingContract/getItemStanda rd/"/>" + id;
var paramStandard = $("select[name='testStandard']");
$.ajax({
url:url,
dataType:'json',
success:function (htmlData) {
var paramStandardA = htmlData.paramStandardA;
paramStandard.innerHTML = paramStandardA;
}
})
}
function addItem(btn){
var items = "<tr>" +
"<td>子选项1:</td>" +
"<td><select class='form-control' name='testParam' requ ired='required' " + "onchange='getStandardA(this)'><opt ion VALUE='0'>请选择自选项1</option></select></td>" +
"<td>子选项2:</td>" +
"<td><select class='form-control' name='testStandard' r equired='required'>" + "<option VALUE='0'>请选择子选项2< /option></select></td>" +
"<td>input框:</td>" +
"<td><input class='form-control' name='judgement' requi red='required' type='text'></td>" +
"<td><button type='button' class='btn btn-default' oncli ck=deleteItems(this) id='deleteBtn'>删除</button></td>"
+"</tr>";
$(".testTable tbody").append(items);
getChildItemA(btn);
}
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一起探讨学习。