-ループ
ループのあたりも含め、ひとまずサーバサイドのコードを書きおえ。Tapestryみたいに二度書きもしないし、サーバサイドでJSF風にループ毎にモデルを増やさない。JSPのELでも透過的にアクセスできる。。。結構いいかもしんない。やってることは、一意に特定できるモデルのパス文字列を作りこむことです。
@PageModel(ModelScope.APPLICATION) public interface TaskModel { void setTask(List<Task> task); List<Task> getTask(); }
@PageModel(ModelScope.INTERNAL) public interface Task { void setDescription(String description); @DateConverter("yyyy/MM/dd") @ErrorMessageTo("dateFormatError") void setRegistDate(Date registDate); String getDateFormatError(); }
こんな、単純なリストを持つモデルを用意して、以下がJSP。
<%@page contentType="text/html; charset=UTF-8"%> <%@taglib prefix="ik" uri="http://ikushipe.ashikunep.org/core"%> <html> <body> <ik:form> <ik:loop property="task"> <ik:input property="task.registDate"/> <ik:input property="task.description"/> <ik:submit event="upTo" caption="up"/> <ik:submit event="downTo" caption="down"/><br> </ik:loop> </ik:form> </body> </html>
これが、
<html> <body> <form action="/context/task/TaskPage"> <input type="text" name="task[0].registDate"/> <input type="text" name="task[0].description"/> <input type="submit" name="upTo/task[0]" value="up"/> <input type="submit" name="downTo/task[0]" value="down"/><br> <input type="text" name="task[1].registDate"/> <input type="text" name="task[1].description"/> <input type="submit" name="upTo/task[1]" value="up"/> <input type="submit" name="downTo/task[1]" value="down"/><br> <input type="text" name="task[2].registDate"/> <input type="text" name="task[2].description"/> <input type="submit" name="upTo/task[2]" value="up"/> <input type="submit" name="downTo/task[2]" value="down"/><br> </form> </body> </html>
を出すイメージ。まだ理論値なんだけど。"task[2].description"は、EL式で${task[2].description}でアクセスできるようにしています。HttpServletRequestWrapperでモデルプロパティをリクエストスコープのもののようにアクセスできる裏口も用意したためです。
サブミットされると、"upTo/task[1]=up"というようなリクエストパラメータの名前と値のセットが飛んできます。これはupToというハンドラメソッドが要求されていて、taskがループしてインデックス値が1ですよ、と知ることができる。受け止める描画ページには、以下のハンドラがあります。
@WebPage(TaskModel.class) public class TaskPage { @LoopName("task") public Class<?> upTo(int index, TaskModel model) { if(index > 0) { List<Task> taskList = model.getTask(); Task task = taskList.remove(index); taskList.add(index -1, task); } return null; } @LoopName("task") public Class<?> downTo(int index, TaskModel model) { List<Task> taskList = model.getTask(); if(taskList.size() -1 > index) { Task task = taskList.remove(index); taskList.add(index + 1, task); } return null; } }
引数には状況に応じて、あたかもDIのようにフレームワークが値をセットしてくれます。このハンドラはnullを返しているので遷移しませんが、ページのクラス型を返すとそのページを示すURLにリダイレクトして、結果、遷移します。