当前位置 : 主页 > 编程语言 > java >

在JSP/Servlet中填充级联下拉列表

来源:互联网 收集:自由互联 发布时间:2021-06-25
假设我有三个名为dd1,dd2和dd3的下拉列表控件。每个下拉列表的值来自数据库。 dd3的值取决于dd2的值,dd2的值取决于dd1的值。任何人都可以告诉我如何调用servlet的这个问题? 基本上有
假设我有三个名为dd1,dd2和dd3的下拉列表控件。每个下拉列表的值来自数据库。 dd3的值取决于dd2的值,dd2的值取决于dd1的值。任何人都可以告诉我如何调用servlet的这个问题? 基本上有三种方法来实现这一点:

>在第一个下拉列表的onchange事件中将表单提交到servlet(可以使用Javascript),让servlet获取第一个下拉列表中选定的项作为请求参数,让它从第二个下拉菜单中获取相关的值数据库作为Map< String,String&gt ;,让它存储在请求范围中。最后让JSP / JSTL在第二个下拉列表中显示值。你可以使用JSTL(只是删除jstl-1.2.jar在/ WEB-INF / lib)c:forEach标签。您可以在与JSP页面相关联的Servlet的doGet()方法中预填充第一个列表。

<select name="dd1" onchange="submit()">
    <c:forEach items="${dd1options}" var="option">
        <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option>
    </c:forEach>
</select>
<select name="dd2" onchange="submit()">
    <c:if test="${empty dd2options}">
        <option>Please select parent</option>
    </c:if>
    <c:forEach items="${dd2options}" var="option">
        <option value="${option.key}" ${param.dd2 == option.key ? 'selected' : ''}>${option.value}</option>
    </c:forEach>
</select>
<select name="dd3">
    <c:if test="${empty dd3options}">
        <option>Please select parent</option>
    </c:if>
    <c:forEach items="${dd3options}" var="option">
        <option value="${option.key}" ${param.dd3 == option.key ? 'selected' : ''}>${option.value}</option>
    </c:forEach>
</select>

但是,一旦警告,这将提交整个表单,并造成一个“内容闪光”,这可能是不好的用户体验。您还需要基于请求参数以相同的形式保留其他字段。您还需要在servlet中确定请求是更新下拉列表(子下拉列表值为null)还是提交实际表单。
>将第2个和第3个下拉菜单的所有可能值作为Javascript对象打印,并使用Javascript函数在第1个下拉列表的onchange事件期间基于第1个下拉列表中选定的项目填充第2个下拉列表。此处不需要提交表单,也不需要服务器循环。

<script>
    var dd2options = ${dd2optionsAsJSObject};
    var dd3options = ${dd3optionsAsJSObject};
    function dd1change(dd1) {
        // Fill dd2 options based on selected dd1 value.
        var selected = dd1.options[dd1.selectedIndex].value;
        ...
    }
    function dd2change(dd2) {
        // Fill dd3 options based on selected dd2 value.
        var selected = dd2.options[dd2.selectedIndex].value;
        ...
    }
</script>

<select name="dd1" onchange="dd1change(this)">
    <c:forEach items="${dd1options}" var="option">
        <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option>
    </c:forEach>
</select>
<select name="dd2" onchange="dd2change(this)">
    <option>Please select parent</option>
</select>
<select name="dd3">
    <option>Please select parent</option>
</select>

然而,一个警告是,这可能会变得不必要地冗长和昂贵,当你有很多的项目。假设您有每100个可能项目的3个步骤,这意味着JS对象中的100 * 100 * 100 = 1,000,000个项目。 HTML页面的长度将超过1MB。
>使用Javascript中的XMLHttpRequest在第一个下拉列表的onchange事件期间向servlet发出异步请求,让servlet获取第一个下拉列表中选定的项作为请求参数,让它获取第二个下拉列表的关联值数据库,将其返回为XML或JSON字符串。最后让Javascript在HTML DOM树的第二个下拉列表中显示值(Ajax方式,如前所述)。最好的方法是使用jQuery。

<%@ page pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>SO question 2263996</title>
        <script src="http://img.558idc.com/uploadfile/allimg/210625/1J2002629-0.jpg"></script>
        <script>
            $(document).ready(function() {
                $('#dd1').change(function() { fillOptions('dd2', this); });
                $('#dd2').change(function() { fillOptions('dd3', this); });
            });
            function fillOptions(ddId, callingElement) {
                var dd = $('#' + ddId);
                $.getJSON('json/options?dd=' + ddId + '&val=' + $(callingElement).val(), function(opts) {
                    $('>option', dd).remove(); // Clean old options first.
                    if (opts) {
                        $.each(opts, function(key, value) {
                            dd.append($('<option/>').val(key).text(value));
                        });
                    } else {
                        dd.append($('<option/>').text("Please select parent"));
                    }
                });
            }
        </script>
    </head>
    <body>
        <form>
            <select id="dd1" name="dd1">
                <c:forEach items="${dd1}" var="option">
                    <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option>
                </c:forEach>
            </select>
            <select id="dd2" name="dd2">
                <option>Please select parent</option>
            </select>
            <select id="dd3" name="dd3">
                <option>Please select parent</option>
            </select>
        </form>
    </body>
</html>

..其中Servlet后面的/ json / options可以看起来像这样:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String dd = request.getParameter("dd"); // ID of child DD to fill options for.
    String val = request.getParameter("val"); // Value of parent DD to find associated child DD options for.
    Map<String, String> options = optionDAO.find(dd, val);
    String json = new Gson().toJson(options);
    response.setContentType("application/json");
    response.setCharacterEncoding("UTF-8");
    response.getWriter().write(json);
}

这里,Gson是Google Gson,这使得将完整的Java对象转换为JSON,反之亦然。参见How to use Servlets and Ajax?

网友评论