dd1
、dd2
、dd3
という名前の3つのドロップダウンリストコントロールがあるとします。各ドロップダウンリストの値はデータベースから取得されます。 dd3
の値はdd2
の値に依存し、dd2
の値はdd1
の値に依存します。この問題のためにサーブレットをどのように呼び出すのですか?
これを実現するには、基本的に3つの方法があります。
1番目のドロップダウンのonchangeイベント中にフォームをサーブレットに送信し(これにJavascriptを使用できます)、1番目のドロップダウンの選択されたアイテムをリクエストパラメーターとしてサーブレットに取得させ、2番目のドロップダウンの関連値をデータベースから取得させます_Map<String, String>
_として、それらを要求スコープに保存します。最後に、JSP/JSTLに2番目のドロップダウンに値を表示させます。使用できます [〜#〜] jstl [〜#〜] (ドロップするだけで jstl-1.2.jar in _/WEB-INF/lib
_) _c:forEach
_ このタグ。 JSPページに関連付けられたServlet
のdoGet()
メソッドで最初のリストを事前に設定できます。
_<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>
_
ただし、これはentireフォームを送信し、ユーザーエクスペリエンスに悪い「コンテンツのフラッシュ」を引き起こすという点に注意してください。また、リクエストパラメータに基づいて、同じフォームの他のフィールドを保持する必要があります。また、リクエストがドロップダウンの更新(子ドロップダウン値がnull)であるか、実際のフォームを送信するかをサーブレットで決定する必要があります。
2番目と3番目のドロップダウンのすべての可能な値をJavascriptオブジェクトとして出力し、Javascript関数を使用して、1番目のドロップダウンのonchangeイベント中に、1番目のドロップダウンの選択項目に基づいて2番目のドロップダウンを埋めます。ここでは、フォームの送信やサーバーサイクルは不要です。
_<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>
_
ただし、多数のアイテムがある場合、これは不必要に長くなり、高価になる可能性があるという注意点があります。 JSオブジェクトに100 * 100 * 100 = 1,000,000個のアイテムが存在する可能性がある100個のアイテムごとに3つのステップがあるとします。 HTMLページの長さは1MBを超えます。
JavascriptのXMLHttpRequestを使用して、最初のドロップダウンのonchangeイベント中にサーブレットへの非同期リクエストを起動し、サーブレットが最初のドロップダウンの選択されたアイテムをリクエストパラメータとして取得し、2番目のドロップダウンの関連する値をデータベース、XMLまたは [〜#〜] json [〜#〜] 文字列として返します。最後に、JavascriptにHTML DOMツリーを介して2番目のドロップダウンに値を表示させます(以前に提案した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>
_
..where _/json/options
_の後ろのServlet
は次のようになります:
_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?
あなたの質問から判断すると、実際にはWebフレームワークを使用しているのではなく、サーブレットを使用してhtmlをレンダリングしています。
私はニースであり、あなたは時代から約10年遅れていると言います:)、人々はこの種のことのためにJSP(およびストラットのようなWebフレームワーク)を使用します。しかし、それを言って、ここに行きます:
繰り返しますが、Webフレームワークを使用するか、少なくとも古いjspを使用してこれを行います。
これには複数のサーブレットが必要になる場合があります。
サーブレット1:最初のドロップダウンリストの値をデータベースからロードします。 JSPページで、ドロップダウンリストを作成します。ユーザーが値を選択すると、サーブレット2に送信されます。
サーブレット2:最初のリストから値を取得し、2番目のリストの値に対してデータベース検索を実行します。 2番目のリストを作成します。ユーザーが2番目の値を選択したら、それをサーブレット3に送信します。
サーブレット3:2番目のドロップダウンで選択した値を取得し、データベース検索を実行して最後のドロップダウンの値を取得します。
AJAXを検討すると、ユーザーにリストのデータがシームレスに表示されるようになります。jQueryには、これを簡単に行うための非常に素晴らしいプラグインがあります。
<form action="servlet2.do">
<select name="dd1" onchange="Your JavaScript Here">
<option>....
</select>
</form>
Onchangeイベントでフォームを送信するJavaScriptを記述できます。繰り返しますが、jQueryのような既存のライブラリを使用すると、10倍簡単になります。
それは素晴らしいシンプルなソリューションでした。私はJQueryコードがどれほど小さいかが好きで、GSON APIへのリンクを本当に感謝しています。すべての例がこれを簡単な実装にしました。
親SELECTへの参照を使用したJSONサーバーURLの作成に関する問題が1つありました(例:$(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>