でjava.util.Mapの内容にアクセスする
Facelets内で使う場合だけではなく本物のJSTLを使う場合でも一緒かもしれないけど。
マニュアルではforEachのitemsはMapも取れることになっているけど、普通にループさせてもvaluesの方しか取り出せない(様に見える。) しかしデバッガで追ってみると、MappedValueExpressionが使われているので、キーにも値にもアクセスできるはず。
ソースを読んでいると、transientアトリビュートが真の場合にはMap.Entry自体が、それ以外の場合はMap.EntryのgetValueの値が使われるようになるようだ。
ForEachHandler.java:apply(): boolean t = this.getTransient(ctx); .... if (t || srcVE == null) { ctx.setAttribute(vs, itrS); } else { ve = new IterationStatusExpression(itrS); vars.setVariable(vs, ve); }
ということで、キー-値のペアとして内容を取り出すにはアトリビュートにtransient="true"を指定すれば良い。(しかしドキュメントには何も書いてない。) 下のようにvarで指定した変数にMap.Entryがセットされてそれに.key、.valueでアクセスできるイメージ。
<c:forEach items="#{map}" var="entry" transient="true"> <div class="entry-key"> <h:outputText value="#{entry.key}" /> </div> <div class="entry-value"> <h:outputText value="#{entry.value}" /> </div> </c:forEach>
これでELがinstanceofに対応してくれたら基本タグだけでMap/Listの中身を再帰的に表示するコンポーネント(というかテンプレート)作れるのに。まあいいや。
ちなみに上のテンプレートでtransientを指定しないと、Bean: java.lang.String, property: valueとかいわれてcom.sun.facelets.tag.TagAttributeExceptionを投げられる。