子タグから親タグのカウンタを見て繰り返し回数を取得する

taglib で繰り返しの出力を行いたい際に、何回目のループなのかを子タグが知る方法が無いのものとかと試行錯誤。Google 先生に聞いてもこれと言って教えてくれなかったので色々やってみた。
例えばこんな感じで属性を作って指定すれば何回目か分かる。

<n:table border="1">
  <% for(int i = 0 ; i < 10 ; i++) { %>
    <td><n:f index="<%= i %>"/></td>
  <% } %>
</n:table>

でもこれってかっこ悪いし属性が増えると可読性も下がる。なので、こんな(↓)風にしたい。

<n:table border="1">
  <n:tr from="0" to="10">
    <td><n:f /></td>
  </n:tr>
</n:table>

これをどう実現するのかが分からなかったので試行錯誤を繰り返してみたらできた。

  • tr のタグの doAfterBody で、指定回数に到達するまでは EVAL_BODY_AGAIN で評価を繰り返す。
  public int doAfterBody() {
    BodyContent body = getBodyContent();
    try {
      JspWriter writer = body.getEnclosingWriter();
      writer.print("<TR>" + body.getString() + "</TR>");
    } catch (IOException e) {
    }
    body.clearBody();

    if(from_ < to_) {
      from_ ++;
      return EVAL_BODY_AGAIN;
    }
    return SKIP_BODY;
  }
  • f のタグで親タグを取得してカウンタを取得して出力する。
TrTag tr = (TrTag)getParent();
int from = tr.getFrom();
try {
  pageContext.getOut().print(from);
} catch(Exception e) {
  e.printStackTrace();
}
return SKIP_BODY;

これで記述量を減らし、可読性を高めて目的のものを作れそうだ。
ちなみにこれの試行錯誤動作確認は SAStruts でやった。サクサク開発で taglib のクラスなんかも直したら即反映だしホントに助かる。会社で使ってるフレームワークは目的の画面に到達するまでに沢山テーブルを読んだりしないといけないからちょっとした修正が痛いんだよなぁ・・・。
コンテナを落として、直して、動作確認できるまでの待ち時間でいろいろ考えられるというメリット(?)もあるんだけども。