Llenar listas desplegables en cascada en JSP/Servlet

Resuelto deven asked hace 14 años • 4 respuestas

Supongamos que tengo tres controles de lista desplegable llamados dd1, dd2y dd3. El valor de cada lista desplegable proviene de la base de datos. dd3El valor de depende del valor de dd2y dd2el valor depende del valor de dd1. ¿Alguien puede decirme cómo llamo al servlet para este problema?

deven avatar Feb 15 '10 11:02 deven
Aceptado

Básicamente, existen tres formas de lograrlo:

  1. Envíe el formulario a un servlet durante el evento de cambio del primer menú desplegable (puede usar Javascript para esto), deje que el servlet obtenga el elemento seleccionado del primer menú desplegable como parámetro de solicitud, déjelo obtener los valores asociados del segundo menú desplegable de la base de datos como Map<String, String>, déjelo almacenarlos en el alcance de la solicitud. Finalmente, deje que JSP/JSTL muestre los valores en el segundo menú desplegable. Puede usar la etiqueta JSTL (simplemente coloque jstl-1.2.jar en /WEB-INF/lib) c:forEachpara esto. Puede completar previamente la primera lista en el doGet()método de Servletla página JSP asociada.

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

    Sin embargo, hay que tener en cuenta que esto enviará el formulario completo y provocará un "destello de contenido" que puede ser perjudicial para la experiencia del usuario. También deberá conservar los demás campos en el mismo formulario según los parámetros de la solicitud. También deberá determinar en el servlet si la solicitud es para actualizar un menú desplegable (el valor del menú desplegable secundario es nulo) o para enviar el formulario real.

  2. Imprima todos los valores posibles del segundo y tercer menú desplegable como un objeto Javascript y utilice una función de Javascript para completar el segundo menú desplegable según el elemento seleccionado del primer menú desplegable durante el evento de cambio del primer menú desplegable. Aquí no es necesario enviar ningún formulario ni realizar ningún ciclo del servidor.

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

    Sin embargo, una advertencia es que esto puede resultar innecesariamente largo y costoso cuando se tienen muchos artículos. Imagina que tienes 3 pasos de cada 100 elementos posibles, eso significaría 100 * 100 * 100 = 1.000.000 de elementos en objetos JS. La página HTML crecería más de 1 MB de longitud.

  3. Utilice XMLHttpRequest en Javascript para activar una solicitud asincrónica a un servlet durante el evento de cambio del primer menú desplegable, deje que el servlet obtenga el elemento seleccionado del primer menú desplegable como parámetro de solicitud, déjelo obtener los valores asociados del segundo menú desplegable del base de datos, devuélvala como cadena XML o JSON . Finalmente, deje que Javascript muestre los valores en el segundo menú desplegable a través del árbol HTML DOM (al estilo Ajax, como se sugirió anteriormente). La mejor manera de hacerlo sería usar 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>
    

    ..donde el Servlettrasero /json/optionspuede verse así:

     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);
     }
    

    Aquí Gsonestá Google Gson , que facilita la conversión de objetos Java completos a JSON y viceversa. Consulte también ¿Cómo utilizar Servlets y Ajax?

BalusC avatar Feb 15 '2010 15:02 BalusC

A juzgar por su pregunta, en realidad no está utilizando un marco web, sino servlets para representar HTML.

Seré amable y diré que estás aproximadamente una década atrasado :), la gente usa JSP (y un marco web como struts) para este tipo de cosas. Sin embargo, dicho esto, ahí va:

  1. Cree un campo oculto en su formulario y establezca el valor en '1', '2' o '3' dependiendo del menú desplegable que se completará;
  2. En su servlet, capture este valor (request.getParamter()) y utilícelo como una declaración 'case'/if/else para devolver los valores desplegables apropiados.

Lo diré de nuevo, simplemente use un marco web, o al menos un jsp antiguo para hacer esto.

Ryan Fernandes avatar Feb 15 '2010 04:02 Ryan Fernandes

Es posible que necesite varios servlets para esto.

Servlet 1: cargue los valores para la primera lista desplegable de la base de datos. En la página JSP, cree la lista desplegable. Cuando el usuario selecciona un valor, envíelo al servlet dos.

Servlet 2: recupere el valor de la primera lista y realice su búsqueda en la base de datos de los valores de la segunda lista. Construya la segunda lista. Cuando el usuario seleccione el segundo valor, envíelo al servlet 3.

Servlet 3: recupera el valor seleccionado en el segundo menú desplegable y realiza la búsqueda en la base de datos para obtener valores para el último menú desplegable.

Es posible que desee considerar AJAX para que el llenado de las listas parezca fluido para los usuarios. jQuery tiene algunos complementos muy buenos para hacer esto bastante fácil si estás dispuesto a hacerlo.


     <form action="servlet2.do">
          <select name="dd1" onchange="Your JavaScript Here">
               <option>....
          </select>
     </form>

Puede escribir JavaScript que envíe el formulario en el evento onchange. Nuevamente, si usa una biblioteca existente como jQuery, será 10 veces más sencillo.

Vincent Ramdhanie avatar Feb 15 '2010 04:02 Vincent Ramdhanie