dd1
、、dd2
およびという名前の3つのドロップダウンリストコントロールがあるとしdd3
ます。各ドロップダウンリストの値はデータベースから取得されます。dd3
の値はの値に依存し、dd2
のdd2
値はの値に依存しますdd1
。この問題に対してサーブレットを呼び出す方法を教えてもらえますか?
4 に答える
これを実現するには、基本的に3つの方法があります。
1番目のドロップダウンのonchangeイベント中にフォームをサーブレットに送信し(これにはJavascriptを使用できます)、サーブレットに1番目のドロップダウンの選択されたアイテムを要求パラメーターとして取得させ、2番目のドロップダウンの関連する値をデータベースから取得させますとして、
Map<String, String>
リクエストスコープに保存します。最後に、JSP/JSTLに2番目のドロップダウンの値を表示させます。これにはJSTL(jstl-1.2.jarをドロップするだけ/WEB-INF/lib
)c:forEach
タグを使用できます。JSPページに関連付けられているdoGet()
メソッドの最初のリストに事前入力できます。Servlet
<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>
ただし、これによりフォーム全体が送信され、ユーザーエクスペリエンスに悪影響を与える可能性のある「コンテンツのフラッシュ」が発生することに注意してください。また、リクエストパラメータに基づいて、他のフィールドを同じ形式で保持する必要があります。また、サーブレットで、リクエストがドロップダウンを更新するのか(子のドロップダウン値が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>
ただし、1つの注意点は、アイテムが多い場合、これが不必要に長く、高価になる可能性があることです。100個の可能なアイテムごとに3つのステップがあると想像してください。つまり、JSオブジェクトには100 * 100 * 100=1,000,000個のアイテムがあります。HTMLページの長さは1MBを超えます。
JavascriptのXMLHttpRequestを使用して、1番目のドロップダウンのonchangeイベント中にサーブレットへの非同期リクエストを起動し、サーブレットが1番目のドロップダウンの選択されたアイテムをリクエストパラメーターとして取得し、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>
..
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
これがGoogleGsonで、十分な価値のあるJavaオブジェクトをJSONに、またはその逆に簡単に変換できます。サーブレットとAjaxの使用方法も参照してください。
このために複数のサーブレットが必要になる場合があります。
サーブレット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倍簡単になります。
あなたの質問から判断すると、あなたは実際にはWebフレームワークを使用しているのではなく、サーブレットを使用してhtmlをレンダリングしています。
私はいいでしょう、そしてあなたは時代から約10年遅れていると言います:)、人々はこの種のことのためにJSP(そして支柱のようなウェブフレームワーク)を使用します。しかし、そうは言っても、ここに行きます:
- フォームに非表示フィールドを作成し、入力するドロップダウンに応じて値を「1」、「2」、または「3」に設定します。
- サーブレットで、この値(request.getParamter())をキャプチャし、それを'case' / if / elseステートメントを使用して、適切なドロップダウン値を返します。
もう一度言いますが、これを行うには、Webフレームワークを使用するか、少なくともプレーンな古いjspを使用します。
それは素晴らしくシンプルな解決策でした。私はJQueryコードがいかに小さいかが好きで、GSONAPIへのリンクに本当に感謝しています。すべての例で、これは簡単な実装になりました。
親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>