Предположим, у меня есть три раскрывающихся списка с именами dd1
, dd2
и dd3
. Значение каждого выпадающего списка исходит из базы данных. Значение dd3
зависит от значения dd2
, а значение dd2
зависит от значения dd1
. Может ли кто-нибудь сказать мне, как мне вызвать сервлет для этой проблемы?
Заполнение каскадных выпадающих списков в JSP/Servlet
Ответы (4)
Есть в основном три способа добиться этого:
Отправьте форму сервлету во время события onchange 1-го раскрывающегося списка (для этого вы можете использовать Javascript), позвольте сервлету получить выбранный элемент 1-го раскрывающегося списка в качестве параметра запроса, пусть он получит связанные значения 2-го раскрывающегося списка из базы данных как
Map<String, String>
, пусть он хранит их в области запроса. Наконец, позвольте JSP/JSTL отображать значения во втором раскрывающемся списке. Вы можете использовать JSTL (просто поместите jstl-1.2.jar в/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>
Однако следует учесть, что это приведет к отправке полной формы и вызовет вспышку содержимого, что может отрицательно сказаться на пользовательском опыте. Вам также потребуется сохранить другие поля в той же форме на основе параметров запроса. Вам также необходимо определить в сервлете, является ли запрос обновлением раскрывающегося списка (значение дочернего раскрывающегося списка равно нулю) или отправкой фактической формы.
Распечатайте все возможные значения 2-го и 3-го раскрывающегося списка в виде объекта Javascript и используйте функцию Javascript для заполнения 2-го раскрывающегося списка на основе выбранного элемента 1-го раскрывающегося списка во время события onchange 1-го раскрывающегося списка. Здесь не требуется отправка формы и цикл сервера.
<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-го раскрывающегося списка, позвольте сервлету получить выбранный элемент 1-го раскрывающегося списка в качестве параметра запроса, позвольте ему получить связанные значения 2-го раскрывающегося списка из базу данных, верните ее обратно в виде строки 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); }
Здесь
Gson
– это Google Gson, который упрощает преобразование полноценных объектов Java в JSON и наоборот. . См. также Как использовать сервлеты и Ajax?
$.getJSON
описано здесь: api.jquery.com/jQuery.getJSON URL просто /json/options
. Также смотрите текст (а не только код). Вы можете просто выбрать любой URL-адрес, который хотите. opts
действительно является строкой JSON, возвращаемой сервлетом. Также см. ссылку JSON, чтобы узнать больше об этом. Если вы хорошо знаете Javabeans, то JSON должен выглядеть достаточно знакомо. $('>option', dd).remove()
удаляет все предыдущие параметры из раскрывающегося списка, иначе он будет только добавляться, добавляться и т. Д. Кстати, если вам нравятся ответы, просто проголосуйте за них. Я вижу, что вы почти никогда не голосовали.
- person BalusC; 28.02.2010
Судя по вашему вопросу, вы действительно не используете веб-фреймворк, а используете сервлеты для рендеринга html.
Я буду мил и скажу, что вы отстали от времени примерно на десятилетие :), люди используют JSP (и веб-фреймворк, такой как struts) для такого рода вещей. Однако, сказав это, вот:
- Создайте скрытое поле в своей форме и установите значение «1», «2» или «3» в зависимости от того, какой выпадающий список должен быть заполнен;
- В своем сервлете зафиксируйте это значение (request.getParamter()) и используйте его в операторе case/if/else для возврата соответствующих выпадающих значений.
Я повторю еще раз, просто используйте для этого веб-фреймворк или, по крайней мере, старый добрый jsp.
Для этого вам может понадобиться несколько сервлетов.
Сервлет 1: загрузить значения для первого раскрывающегося списка из базы данных. На странице JSP создайте раскрывающийся список. Когда пользователь выбирает значение, отправьте сервлету два.
Сервлет 2: получить значение из первого списка и выполнить поиск в базе данных значений второго списка. Составьте второй список. Когда пользователь выбирает второе значение, отправьте его на сервлет 3.
Сервлет 3: получить значение, выбранное во втором раскрывающемся списке, и выполнить поиск в базе данных, чтобы получить значения для последнего раскрывающегося списка.
Вы можете захотеть рассмотреть AJAX, чтобы заполнение списков выглядело бесшовным для пользователей. У jQuery есть несколько очень хороших плагинов, которые упрощают это, если вы готовы это сделать.
<form action="servlet2.do">
<select name="dd1" onchange="Your JavaScript Here">
<option>....
</select>
</form>
Вы можете написать JavaScript, который отправляет форму в событии onchange. Опять же, если вы используете существующую библиотеку, такую как jQuery, это будет в 10 раз проще.
Это было потрясающе простое решение. Мне нравится, насколько мал код JQuery, и я очень ценю ссылку на API GSON. Все примеры сделали это простой реализацией.
Была одна проблема при создании URL-адреса сервера JSON со ссылкой на родительский SELECT (например, $(this).val()
) [необходимо указать атрибут :selected
]. Я немного изменил сценарий, чтобы включить предлагаемые обновления. Спасибо за исходный код.
<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>