明確に描いている記事を見かけなかったので…


テーブル等でデータをループして描画する際、CSSデザインの適用などの問題を考えて
data tableは使わずにすべてui:repeatで描画しているのですが、
その中で気がついたことなどメモ



■JSTLのタグと混ぜて使わない


if文を使いたくて、ui:repeat内でを使ってみたんですが訳の分からないことになった…
どうやら解析のタイミングに違いがあるようで、JSF→JSTの順だったかな?
になるため、repeatしてからif文の解釈されるので、全行に最終行の結果が反映される事態に。
素直にui:fragmentを使いましょう。チャンポンダメ・ゼッタイ


■RequestScopeの場合は、毎回初期化&必要件数のインスタンス化が必要


ViewScope以上なら気にすることはありません。
Springとの連携をしている影響で、ViewScopeが使えないため起こった事態。
ui:repeatで画面に描画した後になにかしらボタンを押してrequestを投げ、
なんやかんやして同じ画面に戻ってくる、という処理をしたかったわけですが。
ループ内にhidden項目を突っ込むだけでは、Bean内のListを再構築してくれませんでした…
どうも、突っ込むための枠は作ってくれないご様子。
枠があれば突っ込まれてくれる。
(Beanのコンストラクタ内で固定で3つインスタンスをaddしたら受け取ってくれた)
しかし、動的に行数が変わるし、コンストラクタも@PostConstract
Beanへのパラメータセット前に動かされるから、パラメータで行数を渡すこともできない

ええいこうなったらSessionScopeだ…の前に、ExternalContextを試すことに。

commandButton内でf:paramを使うと、特定のボタンを押したときだけhiddenでパラメータを渡すことができます。
※今回はどのボタンからも渡したかったので、普通にinput type="hidden"を使いましたが。
こういった形で私たパラメータは、ExternalContextを介してGet出来ます

こんなかんじ
FacesContext context = FacesContext.getCurrentInstance();
String value = context.getExternalContext().getRequestParameterMap().get("value");


これなら
@PostConstruct内で、画面に表示した行数がわかる!ということで、
画面側で行数を適当なinput hiddenに放り込んで、上記の方法で取得して、
取得した件数分ループさせてListにインスタンスをぶっこむ、という方法を取りました。

この辺もうちょっと、もうちょっと何とかしてくれないかなあ


ちなみに、このあたりはコンボボックスも同じような感じ。
めんどくせえ…
コンボボックスの選択肢生成にf:selectItems等を利用する場合、
@PostConstructで該当のリストを生成していないとバリデーション?エラーになるというお話。
そんな値存在しません!みたいなエラーで怒られる
単純な名称のリストとかなら@PostConstruct内でDB見に行くなりすればいいんだけど、その時画面に表示している値によってコンボの内容を切り替えなきゃいけないような場合、どーすんの?と思った。
必要なパラメータだけsessionに突っ込んでおくか、上記のExternalContextを利用するしかなさげ。

ある意味厳密にチェックしてくれるから便利な側面もあるんだろうけど、個人的にはめんどい。


ui:repeat内のパラメータの渡し方


ui:repeat value="#{hogehoge.dataList}" var="data" varStatus="stat"
のようにすると、dataを使ってパラメータにアクセスできるようになるけど、
描画やActionへのパラメータ渡しならともかく、h:inputHiddenでは使えない。
#{hogehoge.dataList[stat.index].value}のように、indexを使ってセットする必要があり。



ui:repeat内のパラメータをアクションの引数に渡すこと


描画側にしか使わないから!と、Bean側のListの初期化を怠っていると
アクションパラメータにセットした値が渡されないのである。
いやこれは本当わからなかった。
たとえば、
ui:repeat value="#{hogehoge.dataList}" var="data" varStatus="stat"
としてあって、
h:commandLink action="#{hogehoge.register(data.value)}"
みたいなことがしたかった場合、このdataListのvalueが、h:inputHiddenを使ってちゃんとBeanに再構成されるようになっていないと動作しない。
展開後のソース見てもいまいちピンとこなかったけど、どうやらaction内に定義した内容って、画面側で展開してどうにかしているわけじゃなくて、一回サーバーに返してサーバー上でデータとって来たりなんなりして、再解析?して動かしてるっぽい。
そのため、引数として渡すパラメータもちゃんとBeanに再構築されていないとnullが渡ってしまうという。

もっかい言うけどめんどくせえ