jsp servlets drop-down-menu cascading

Llenar listas desplegables en cascada en JSP/Servlet



servlets drop-down-menu (4)

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


A juzgar por su pregunta, en realidad no está utilizando un marco web, sino que usa servlets para renderizar html.

Seré amable y diré que estás a una década de los tiempos :), la gente usa JSP (y un framework web como struts) para este tipo de cosas. Sin embargo, una vez dicho esto, aquí va:

  1. Cree un campo oculto en su formulario y establezca el valor en ''1'', ''2'' o ''3'' dependiendo de qué menú desplegable se debe llenar;
  2. En su servlet, capture este valor (request.getParamter ()) y utilícelo como una instrucción ''case'' / if / else para devolver los valores desplegables correspondientes.

Lo diré nuevamente, solo use un framework web, o al menos simple jsp viejo para hacer esto.


Básicamente hay tres formas de lograr esto:

  1. Enviar formulario a un servlet durante el evento onchange 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, permita que obtenga los valores asociados del segundo menú desplegable de la base de datos como un 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 JSTL (simplemente suelte jstl-1.2.jar en /WEB-INF/lib ) c:forEach etiqueta para esto. Puede doGet() la primera lista en el método doGet() del Servlet asociado a la página 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>

    Sin embargo, una advertencia es que esto enviará el formulario completo y causará un "destello de contenido" que puede ser malo para la Experiencia de usuario. También necesitará retener los otros campos en el mismo formulario en función de los parámetros de solicitud. También deberá determinar en el servlet si la solicitud es para actualizar un menú desplegable (el valor desplegable del elemento secundario es nulo) o para enviar el formulario real.

  2. Imprima todos los valores posibles del segundo y tercer desplegable como un objeto Javascript y haga uso de una función de Javascript para completar el segundo menú desplegable en función del elemento seleccionado del primer menú desplegable durante el evento onchange del primer menú desplegable. No se envía ningún formulario y no se necesita un ciclo de servidor aquí.

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

    Una advertencia es, sin embargo, que esto puede ser innecesariamente largo y caro cuando tienes muchos artículos. Imagine que tiene 3 pasos de cada 100 elementos posibles, que significaría 100 * 100 * 100 = 1,000,000 de elementos en objetos JS. La página HTML crecerá más de 1 MB de longitud.

  3. Utilice XMLHttpRequest en Javascript para activar una solicitud asíncrona a un servlet durante el evento onchange del primer menú desplegable, permita que el servlet obtenga el elemento seleccionado del primer menú desplegable como parámetro de solicitud, permita que obtenga los valores asociados del segundo menú desplegable del base de datos, devuélvala como cadena XML o JSON . Finalmente, permita que Javascript muestre los valores en el segundo menú desplegable a través del árbol HTML DOM (el modo Ajax, como se sugirió anteriormente). La mejor forma de hacerlo sería usando 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 las opciones de Servlet behind /json/options pueden 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í, Gson es Google Gson, que facilita la conversión de objetos de Java completos a JSON y viceversa. Ver también ¿Cómo usar los servlets y Ajax?


Es posible que necesite múltiples servlets para esto.

Servlet 1: cargue los valores de la primera lista desplegable de la base de datos. En la página JSP construye la lista desplegable. En el usuario seleccionando un valor enviar a servlet dos.

Servlet 2: recupera el valor de la primera lista y realiza la búsqueda en la base de datos de los valores de la segunda lista. Construye la segunda lista. Cuando el usuario selecciona el segundo valor, preséntelo 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 los valores del último menú desplegable.

Es posible que desee considerar AJAX para que la población de las listas se muestre sin problemas a los usuarios. jQuery tiene algunos complementos muy buenos para hacer esto bastante fácil si estás dispuesto a hacer eso.

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


Esa fue una solución simple increíble. Me gusta lo pequeño que es el código JQuery y realmente aprecio el enlace a la API GSON. Todos los ejemplos hicieron de esto una implementación fácil.

Tuve un problema al construir el URL del servidor JSON con la referencia al padre SELECT (por ejemplo $(this).val() ) [necesario para especificar el atributo :selected ]. Modifiqué un poco el guión para incluir las actualizaciones sugeridas. Gracias por el código inicial.

<script> $(document).ready(function() { $(''#dd1'').change(function() { fillOptions(''dd1'', ''dd2''); }); $(''#dd2'').change(function() { fillOptions(''dd2'', ''dd3''); }); }); function fillOptions(parentId, ddId) { var dd = $(''#'' + ddId); var jsonURL = ''json/options?dd='' + ddId + ''&val='' + $(''#'' + parentId + '' :selected'').val(); $.getJSON(jsonURL, 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>