フォーム一つ+複数のページ

何のことか分からない人へ: wizard-like page、もしくはmulti-pagesのこと。(最初からそう書け?) もう少し説明してみると、フォームが複数のページにまたがってて、ステップ1が終わったら"次へ"ボタンを押してステップ2にいって…て、あれのことだ。方法はいろいろあるが、一番シンプルだと思われるやり方を書いてみる。 ActionFormをセッションスコープに保存すると簡単に処理できるが、メインテナンスの面からもそれはできるだけ避けたい。
サンプルでは、最初のページで名前とメールアドレスを入れる→次のページでコメントをいれて送信、というシナリオだとしよう。ここではシンプルなので、ひとつのJSPページでステップによって表示するフォームをかえることにする。 まずフォームの作成。プロパティにはname, email, comment, それとpageというプロパティを追加。せっかくなので、DynaValidatorFormを使ってみる。







<form-property name="page" type="java.lang.Integer" initial="1" />

...

<action path="/contact"
forward="contact.web" />
<action path="/contact/submit"
type="actions.ContactForm"
name="contactForm"
validate="true"
input="/contact.do"
scope="request" />



...
DynaValidationFormを使う時はpageプロパティはjava.lang.Integerでなければならないので注意。 そしてvalidation.xmlでは次のようにしてページごとのバリデーションを行う。


<form name="contactForm">









</form>

pageを設定することで、バリデートするプロパティをページごとに指定できる。
次はJSPページ。

←ここはできればhtml:messageを使おう

お問い合わせ:


お名前:
メールアドレス:






コメント:




JSTLを使わないなら、おおまかにこんな感じ。
そしてアクション。

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ContactAction extends Action{

public ActionForward execute (ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
DynaActionForm contactForm = (DynaActionForm) form;

Integer page = (Integer) contactForm.get("page");

//最初のページの時はpageを"2"にセットして次へ
if(page.intValue() == 1){
contactForm.set("page", new Integer(2));
return mapping.findForward("next");
}

//pageが"1"でないので実際のアクションをして終了。
return mapping.findForward("success");
}

}

すごく簡単にまとめてみた。 でも気づいただろうか、これでは実際のアプリケーションでは使えない。なぜって、ステップ2で"戻るボタン"がないのだ。 ボタンを足せばいいじゃないかと思うが、それだけではダメなのだ。なぜって、ステップ2でバリデーションを行うようにしているので、戻るボタンを押してもコメントをうめない限りバックしてくれないのだ。 (なんて実用的じゃないんだ…) なので、複数ページでそれぞれバリデーションをしたいという場合はDynaValidatorFormのサブクラスでバリデーションのメソッドをオーバーライドして処理するか、もしくはアクション内で処理するかのどちらかになる。後、最初からDynaActionFormを使わずに自分でFormクラスを作ってバリデーションもそこでやる、という方法もあり。最初からその方法でやれって?

もっと複雑なワークフローが必要な方は一度Struts Workflow Extension[livinglogic.de]をチェックしてみてはどうだろう。