Предположим, что у меня есть три элемента управления dropdownlist с именем dd1
, dd2
и dd3
. Значение каждого раскрывающегося списка поступает из базы данных. Значение dd3
зависит от значения dd2
и dd2
зависит от значения dd1
. Может ли кто-нибудь сказать мне, как я могу вызвать сервлет для этой проблемы?
Заполнение каскадных выпадающих списков в JSP/Servlet
Ответ 1
Существует три способа достижения этого:
-
Отправьте форму сервлету во время события onchange первого выпадающего списка (вы можете использовать Javascript для этого), пусть сервлет получит выбранный элемент 1-го раскрывающегося списка в качестве параметра запроса, пусть он получит связанные значения второй выпадающий список из базы данных как
Map<String, String>
, пусть он сохранит их в области запроса. Наконец, пусть JSP/JSTL отображает значения во втором раскрывающемся списке. Вы можете использовать JSTL (просто снимите jstl-1.2.jar in/WEB-INF/lib
)c:forEach
для этого. Вы можете предварительно заполнить 1-й список в методе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>
Как только предостережение, тем не менее, оно отправит форму целиком и вызовет "флэш-контент", который может быть плохим для User Experience. Вам также необходимо сохранить другие поля в той же форме на основе параметров запроса. Вам также необходимо определить в сервлете, нужно ли обновлять раскрывающийся список (выпадающее значение дочернего элемента равно null) или отправить фактическую форму.
-
Распечатайте все возможные значения 2-го и 3-го выпадающих списков в качестве объекта Javascript и используйте функцию Javascript, чтобы заполнить второе раскрывающееся меню на основе выбранного пункта 1-го раскрывающегося списка во время события onchange первого выпадающего списка, Никакая форма не отправляется и серверный цикл не требуется.
<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>
Одно из предостережений заключается в том, что это может стать излишне длинным и дорогостоящим, если у вас много элементов. Представьте, что у вас есть 3 шага по 100 возможных предметов, что означает 100 * 100 * 100 = 1 000 000 предметов в объектах JS. HTML-страница будет расти более 1 МБ.
-
Использовать XMLHttpRequest в Javascript для запуска асинхронного запроса на сервлет во время события onchange первого выпадающего списка, пусть сервлет получает выбранный элемент 1-го раскрывающегося списка в качестве параметра запроса, позволяет получить связанные значения 2-го выпадающего списка из базы данных, верните его как XML или JSON string. Наконец, пусть 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); }
Здесь
Gson
Google Gson, который упрощает преобразование полноправных объектов Java в JSON и наоборот. См. Также Как использовать сервлеты и Ajax?
Ответ 2
Для этого может потребоваться несколько сервлетов.
Servlet 1: Загрузите значения для первого выпадающего списка из базы данных. На странице JSP создайте раскрывающийся список. При выборе пользователем значения для сервлета два.
Servlet 2: извлеките значение из первого списка и выполните поиск в базе данных для значений второго списка. Постройте второй список. Когда пользователь выбирает второе значение, отправьте его на сервлет 3.
Сервлет 3: выберите значение, выбранное во втором раскрывающемся списке, и выполните поиск в базе данных, чтобы получить значения для последней выпадающей страницы.
Возможно, вы захотите рассмотреть возможность использования AJAX для того, чтобы заполнение списков было понятным пользователям. В jQuery есть несколько очень приятных плагинов, чтобы сделать это довольно легко, если вы готовы это сделать.
<form action="servlet2.do">
<select name="dd1" onchange="Your JavaScript Here">
<option>....
</select>
</form>
Вы можете написать JavaScript, который отправит форму в событие onchange. Опять же, если вы используете существующую библиотеку, например jQuery, она будет в 10 раз проще.
Ответ 3
Судя по вашему вопросу, вы действительно не используете веб-фреймворк, но используете сервлеты для рендеринга html.
Я буду красив и скажу, что вы отстали примерно на десять лет:), люди используют JSP (и веб-фреймворк, например, struts) для такого рода вещей. Однако, сказав это, здесь говорится:
- Создайте скрытое поле в своей форме и установите значение "1", "2" или "3" в зависимости от того, какой выпадающий список должен быть заполнен;
- В своем сервлете запишите это значение (request.getParamter()) и используйте для него соответствующие аргументы инструкции case/if/else.
Я скажу это снова, просто используйте веб-фреймворк или, по крайней мере, простой старый jsp, чтобы сделать это.
Ответ 4
Это было простое простое решение. Мне нравится, насколько небольшой код JQuery и действительно ценен ссылка на API GSON. Все примеры сделали это простой реализацией.
Возникла одна проблема при создании URL-адреса сервера JSON со ссылкой на родительский SELECT (например, $(this).val()
) [для указания атрибута :selected
]. Я немного изменил script, чтобы включить предлагаемые обновления. Спасибо за исходный код.
<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>