メンチカツには醤油でしょ!!

ITエンジニア徒然 (AWS/Java/JavaScript/Google Spreadsheets/Jenkins/Mac/外部コミュニティ・勉強会レポ)

Struts2の<s:append>が不便なので<s:set>で代用した

コンポーネントに値を渡す時に

画面パーツなどをコンポーネント化してその中に値を渡す時にはJSPでは

<s:push value="#{ 'beanVar':myCompBean, 'beanName':'myCompBean', 'id':'my_comp' }">
  <s:include value="/parts/my_component.jsp" />
</s:push>

とかやってると思います。

MyAction.java (処理もあるけど値の宣言のみ抜粋)

@Getter @Setter
private MyComponentBean myCompBean;

MyComponentBean.java は普通にPOJO

@Getter @Setter
private String value1;
@Getter @Setter
private String value2;

この場合、my_component.jsp ではそのパーツ部分の定義として

<s:textfield name="%{beanName}.value1" value="%{beanVar.value1}" id="%{id}" />
<s:hidden name="%{beanName}.value2" value="%{beanVar.value2}" id="%{id}" />

のように実装すると思いますが、この時に同じくjsのコードも入れたいだとかjsのコードはレンダリングされた全文ソースの最後尾に書かれるように、この時点ではスタックだけしておきたいってことがあると思います。

<s:append>不便

スタックしていくので追加だろーと思って<s:append>で試行錯誤していたのですが、<s:append>がどーも使いにくい。もはや使ってはいけないレベル…

<s:append var="customListIterator">
  <s:param value="%{list1}" />
  <s:param value="%{list2}" />
  <s:param value="%{list3}" />
</s:append>

<ol>
  <s:iterator value="%{#customListIterator}">
    <li><s:property /></li>
  </s:iterator>
</ol>

www.mkyong.com

ここを見るとシンプルな処理で、これでリストとして追加できるように思えるのですが、実際動かしてみると

param with value resolved as 【変数名】 cannot be make as iterator, it will be ignored and hence will not appear in the merged iterator

とコンソールにこっそり出て処理されず。Mapじゃないとダメな感じ。。
配列かリストでappendしたいのに。

しょうがないのでMapで

配列にできなければ仕方なし、Mapにしましょう。ってことで

<s:append var="contents">
  <s:param value="#{'key':#content1}" />
</s:append>
<s:iterator value="%{#contents.{#this.value}}" var="element">
  <s:property value="element" />
</s:iterator>

と書いてみた。
"%{#contents.{#this.value}}" のあたりとか苦労しましたけどね。
しかし、問題はまだあるのでした。

<s:append>2回やってもappendされない問題

画面パーツとしてコンポーネント化しているので当然ですが複数回呼び出されることも考慮しなければなりません。つまり

<s:append var="contents">javascript1</s:append>
<s:append var="contents">javascript2</s:append>

これをレンダリングするとjavascript1と2が2回書かれないといけないのですが、なりません、全然ダメ
で、どうしたかというと

<s:set var="con1">javascript content 1</s:set>
<s:append var="contents">
  <s:param value="contents" />
  <s:param value="#{'key':#con1}" />
</s:append>

<s:set var="con2">javascript content 2</s:set>
<s:append var="contents">
  <s:param value="contents" />
  <s:param value="#{'key':#con2}" />
</s:append>

<s:iterator value="%{#contents.{#this.value}}" var="element">
  <s:property value="element" />
</s:iterator>

工工工エエエエエエェェェェェェ(゚Д゚)ェェェェェェエエエエエエ工工工
できたけどappendじゃないじゃん。setじゃん。

結局<s:set>を使用

<s:set var="contents">${contents}
javascript content 1
</s:set>
<s:set var="contents">${contents}
javascript content 2
</s:set>

<s:property value="contents" />

<s:append>は手数が多くなりすぎるので使っちゃダメな気がする。