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

标签 jsp servlets drop-down-menu cascading

假设我有三个名为 dd1dd2dd3 的下拉列表控件。每个下拉列表的值来自数据库。 dd3 的值取决于 dd2 的值,dd2 的值取决于 dd1 的值。谁能告诉我如何调用 servlet 来解决这个问题?

最佳答案

基本上有三种方法可以实现这一目标:

  1. 在第一个下拉列表的 onchange 事件期间向 servlet 提交表单(可以使用 Javascript),让 servlet 获取第一个下拉列表的所选项目作为请求参数,让它获取关联值数据库中的第二个下拉列表为 Map<String, String> ,让它将它们存储在请求范围内。最后让 JSP/JSTL 显示第二个下拉列表中的值。您可以使用JSTL (只需将 jstl-1.2.jar 放入 /WEB-INF/lib ) c:forEach 为此标记。您可以预填充 doGet() 中的第一个列表。 Servlet的方法与 JSP 页面关联。

     <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. 将第二个和第三个下拉列表的所有可能值打印为 Javascript 对象,并在第一个下拉列表的 onchange 事件期间,使用 Javascript 函数根据第一个下拉列表的所选项目填充第二个下拉列表。这里不需要提交表单,也不需要服务器周期。

     <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。

  3. 利用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://code.jquery.com/jquery-latest.min.js"></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);
     }
    

    在这里,GsonGoogle Gson这可以轻松地将完整的 Java 对象转换为 JSON,反之亦然。另请参阅How to use Servlets and Ajax?

关于jsp - 在 JSP/Servlet 中填充级联下拉列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2263996/

相关文章:

java - JSP获取参数

java - 有没有办法使用 ftm 消息标签作为标题?

java - 如何使用 sendRedirect() 发送变量

java - XMLEntityScanner.peekChar 从 HttpRequest 读取 XML 时出现 ArrayIndexOutOfBoundsException

javascript - 如何修复浏览按钮的初始 uri

jquery - 获取具有特定类名的所有选择下拉列表的正确 jquery 选择器是什么?

java - SQL查询返回 "oracle.jdbc.driver.OracleResultSetImpl@48f675"而不是我预期的数据

java - 如果路径值为空,则设置默认值

html - css 菜单对齐和字间距问题

CSS - 多列子菜单偏移问题