Le remplissage des listes déroulantes en cascade en JSP/Servlet

supposons que j'ai trois contrôles dropdownlist nommés dd1 , dd2 et dd3 . La valeur de chaque dropdownlist provient de la base de données. La valeur de dd3 dépend de la valeur de dd2 et la valeur de dd2 dépend de la valeur de dd1 . Est-ce que quelqu'un peut me dire comment appeler servlet pour ce problème?

38
demandé sur BalusC 2010-02-15 07:01:12

4 réponses

Il y a essentiellement trois façons d'y parvenir:

  1. soumettre un formulaire à un servlet lors de l'événement onchange de la 1ère descente (vous pouvez utiliser Javascript pour cela), laisser le servlet obtenir l'élément sélectionné de la 1ère descente comme paramètre de demande, lui laisser obtenir les valeurs associées de la 2ème descente à partir de la base de données comme un Map<String, String> , le laisser les stocker dans le champ de la requête. Enfin, laissez JSP / JSTL afficher les valeurs de la 2ème déroulante. Vous pouvez utiliser JSTL (il suffit de laisser tomber jstl-1.2.jar in /WEB-INF/lib ) c:forEach une étiquette pour ça. Vous pouvez pré-remplir la 1ère liste de la méthode doGet() de la méthode Servlet associée à la page 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>
    

    une fois que la mise en garde est toutefois que cela va soumettre le entier formulaire et causer un "flash de contenu" qui peut être mauvais pour L'expérience de l'utilisateur. Vous devrez également conserver les autres champs du même formulaire en fonction des paramètres de la requête. Vous devrez également déterminer dans la servlet si la demande est de mettre à jour une liste déroulante (enfant déroulante valeur est nulle) ou pour soumettre le formulaire.

  2. imprimez toutes les valeurs possibles du 2e et du 3e dropdown en tant qu'objet Javascript et utilisez une fonction Javascript pour remplir le 2e dropdown basé sur l'élément sélectionné du 1er dropdown pendant l'évènement onchange du 1er dropdown. Aucune soumission de formulaire et aucun cycle de serveur n'est nécessaire ici.

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

    une mise en garde est cependant que cela peut devenir inutilement long et coûteux quand vous avez un lot d'articles. Imaginez que vous avez 3 étapes de chaque 100 éléments possibles, qui signifierait 100 * 100 * 100 = 1 000 000 d'articles dans les objets JS. La page HTML augmenterait de plus de 1MB de longueur.

  3. Utilisez XMLHttpRequest en Javascript pour lancer une requête asynchrone à un servlet lors de l'événement onchange de la 1ère descente, laissez le servlet obtenir l'élément sélectionné de la 1ère descente comme paramètre de requête, laissez-le obtenir les valeurs associées de la 2ème descente à partir de la base de données, le retourner comme XML ou JSON string. Pour finir, laissez Javascript afficher les valeurs de la deuxième liste déroulante dans L'arborescence du DOM HTML (à la façon Ajax, comme suggéré plus haut). Le meilleur moyen pour il s'agirait de 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>
    

    ..où le Servlet derrière /json/options peut ressembler à ceci:

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

    ici, Gson est Google Gson qui facilite la conversion fullworthy objets Java en JSON et vice versa. Voir aussi comment utiliser Servlets et Ajax?

48
répondu BalusC 2017-05-23 12:09:42

à en juger par votre question, vous n'utilisez pas un framework web, mais des servlets pour rendre html.

je vais être gentil et dire que vous êtes environ une décennie de retard :), les gens utilisent JSPs (et un cadre de web comme struts) pour ce genre de chose. Cependant, cela dit, Voici ce qui suit:

  1. créez un champ caché dans votre formulaire et définissez la valeur à '1', '2' ou '3' en fonction de la chute à remplir;
  2. dans votre servlet, saisissez cette valeur (request.getParamter ()) et utilisez une instruction 'case'/if/else pour retourner les valeurs de dropdown appropriées.

je le répète, il suffit d'utiliser un web-framework, ou du moins simple Vieux jsp pour le faire.

4
répondu Ryan Fernandes 2010-02-15 04:53:17

vous pouvez avoir besoin de plusieurs servlets pour cela.

Servlet 1: Charger les valeurs de la première liste déroulante à partir de la base de données. Sur la page JSP construisez la liste déroulante. Sur l'utilisateur choisissant une valeur soumettre à servlet deux.

Servlet 2: récupérez la valeur de la première liste et effectuez votre recherche dans la base de données pour les valeurs de la deuxième liste. Construisez la deuxième liste. Lorsque l'utilisateur sélectionne la deuxième valeur de la soumettre à servlet 3.

Servlet 3: récupérez la valeur sélectionnée dans la seconde goutte et effectuez la recherche dans la base de données pour obtenir les valeurs de la dernière goutte.

vous pouvez envisager AJAX pour faire le peuplement des listes semblent sans couture aux utilisateurs. jQuery a quelques très jolis plugins pour rendre cela assez facile si vous êtes prêt à le faire.


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

vous pouvez écrire JavaScript qui soumet le formulaire dans le l'événement onchange. Encore une fois, si vous utilisez une bibliothèque existante comme jQuery, ce sera 10 fois plus simple.

4
répondu Vincent Ramdhanie 2015-12-17 22:16:19

Qui était une excellente solution simple. J'aime à quel point le code JQuery est petit et j'apprécie vraiment le lien vers L'API GSON. Tous les exemples en ont facilité la mise en œuvre.

avait un problème lors de la construction de l'URL du serveur JSON avec la référence à la sélection de parent ( par exemple $(this).val() ) [nécessaire pour spécifier l'attribut :selected ]. J'ai un peu modifié le script pour inclure les mises à jour suggérées. Merci pour le code initial.

<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>
3
répondu StephenB 2012-12-09 02:19:37