2008年5月26日月曜日

Spring MVCでチェックボックスを使う(2)~解説

前の投稿のままではあまりに不親切なのでポイントを絞って解説します。

【SelectProducts.java】
 private int[] ids = null;

チェックボックスは配列に格納されるハズだという直感に従い int[] ids を定義しました。
(全体を精読できてはいませんがドキュメントにはこのような記載はなかったはず・・・)

【SelectInventorysFormController.java】
 protected ModelAndView onSubmit(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws Exception {
SelectProducts sp = (SelectProducts) command;
HttpSession session = request.getSession();
session.setAttribute("SelectProducts", sp);
return new ModelAndView(new RedirectView(getSuccessView()));
}

選択された"ids"を次画面に引き渡すため、オブジェクトをSessionに登録しておきます。

【selectproducts.jsp】
    <form:form method="post" commandName="selectProducts">
<c:forEach items="${selectProducts.products}" var="prod" varStatus="row">
<input type="checkbox" id="ids" name="ids" value="<c:out value="${prod.id}"/>">
<c:out value="${prod.description}"/>
<i>$<c:out value="${prod.price}"/></i><br><br>
</c:forEach>
<input type="submit" align="center" value="Execute">
</form:form>

ゴリゴリとチェックボックスを生成しています。
出来上がりは以下のようになります。
    <form id="selectProducts" action="/springapp/selectproducts.htm" method="post">
<input type="checkbox" id="ids" name="ids" value="1">
Lamp
<i>$10.0</i><br><br>
<input type="checkbox" id="ids" name="ids" value="2">
Table
<i>$10.0</i><br><br>
<input type="checkbox" id="ids" name="ids" value="3">
Chair
<i>$10.0</i><br><br>
<input type="submit" align="center" value="Execute">
</form>


【SetPrices.java】
 private List<Product> products = new ArrayList<Product>();
private int[] ids = null;
private String[] descriptions = null;
private double[] prices = null;
private static final int DEFALUT_NUM = 3;
private int position = 0;

後日検証する予定ですが、ids, descriptions, prices, positionは不要と思われます。

【SetPricesValidator.java】
 public void validate(Object obj, Errors errors) {
SetPrices ps = (SetPrices) obj;
for (Product product : ps.getProducts()) {
logger.info("Validating ...");
if (product.getPrice() == null) {
logger.info("Price is null.");
errors.rejectValue("prices", "error.price-not-specified", null,
"Value required.");
} else {
logger.info(product);
if (product.getPrice() <= minPrice) {
errors.rejectValue("prices", "error.too-cheap",
new Object[] { new Integer(minPrice) },
"Value too low.");
}
}
logger.info("Validation end.");
}
}

直感的に納得できるコーディングに落ち着きました。さすがSpringと思っています。

【SetPricesFormController】
 protected Object formBackingObject(HttpServletRequest request)
throws ServletException {
SetPrices ret = new SetPrices();
SelectProducts sp = (SelectProducts) request.getSession().getAttribute(
"SelectProducts");
int[] i = sp.getIds();
for (Product product : productManager.getProducts()) {
for (int j = 0; j < i.length; j++) {
if (product.getId() == i[j]) {
ret.addProduct(product);
break;
}
}
}
return ret;
}

(List)SetPrices.getProducts()で取るための事前の仕込みです。
このようにしておけば後述の"<c:forEach items="${setPrices.products}" varStatus="row">"でJSPからアクセスできます。(これはJSTLのデザインが素晴らしいですね)
 public ModelAndView onSubmit(Object command) throws ServletException {
List<Product> products = ((SetPrices) command).getProducts();

for (Product product : products) {
productManager.setPrice(product.getId(), product.getPrice());
}

return new ModelAndView(new RedirectView(getSuccessView()));
}

絶対上手く行かないだろうと思っていたのでList<Product> products = ((SetPrices) command).getProducts(); でproductsが取れるのには驚きました。素晴らしい。

【setprices.jsp】
<form:form method="post" commandName="setPrices">
<c:forEach items="${setPrices.products}" varStatus="row">
<spring:bind path="setPrices.products[${row.index}].id">
<input type="hidden"
name="<c:out value="${status.expression}"/>"
id="<c:out value="${status.expression}"/>"
value="<c:out value="${status.value}"/>" />
</spring:bind>
<spring:bind path="setPrices.products[${row.index}].description">
<c:out value="${status.value}"/>
</spring:bind>
<spring:bind path="setPrices.products[${row.index}].price">
<input type="text"
name="<c:out value="${status.expression}"/>"
id="<c:out value="${status.expression}"/>"
value="<c:out value="${status.value}"/>" />
</spring:bind>
<br>
</c:forEach>
<form:errors path="prices" cssClass="error"/>

上記タグによって、以下のHTMLが生成されました。(全てにチェックを入れたパターン。もちろんチェックされ具合によって動的にリストが変わります。)
<form id="setPrices" action="/springapp/setprices.htm" method="post">
<input type="hidden"
name="products[0].id"
id="products[0].id"
value="1" />
Lamp
<input type="text"
name="products[0].price"
id="products[0].price"
value="10.0" />
<br>
<input type="hidden"
name="products[1].id"
id="products[1].id"
value="2" />
Table
<input type="text"
name="products[1].price"
id="products[1].price"
value="10.0" />
<br>
<input type="hidden"
name="products[2].id"
id="products[2].id"
value="3" />
Chair
<input type="text"
name="products[2].price"
id="products[2].price"
value="10.0" />
<br>
<br>
<input type="submit" align="center" value="Execute">
</form>

以上。

0 件のコメント: