先日以下@sk44_さんのブログ記事を読んで、そういえばJSFのid周りって何かと色々あるよなぁ…と、今まで開発してて思いつつ、少しまとめてみようかなと思います。
そもそもJSFってなんぞや…ってことについては、最近Oracleさんから以下記事が出てたりするので、その辺りが基礎編としてはいいのかなと。Java EE7ではなく6ですが…(^^;
定義のひな形
以降色々と試してるxhtmlの定義は以下のような形をベースにしました。
とりあえず使ったのはJava EE6です(^^;すみません。
xml version='1.0' encoding='UTF-8'
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlnsh="http://java.sun.com/jsf/html">
<hhead>
<title>例題に合わせて変更</title>
</hhead>
<hbody>
</hbody>
</html>
id属性を指定しない場合
formにもinputTextにもid属性を付与せずに定義。
<hform>
<hinputText />
</hform>
レンダリングされたxhtmlからテキスト部分だけを抜いてみると
<input type="text" name="j_idt7:j_idt8">
idはなく、適当に(数字は全体におけるタグの番号?)付番されたnameがついてます。
id属性を指定した場合
formとinputTextにid属性を指定します。
<hform id="frm">
<hinputText id="txt"/>
</hform>
結果、コロンでformのidとtextのidが連結されて生成されています。
<input id="frm:txt" type="text" name="frm:txt">
FormタグのprependIdをfalseにした場合
formのidを連結しなくていいんだけど…という場合にはformタグのprependId属性をfalseにすると
<hform id="frm" prependId="false">
<hinputText id="txt"/>
</hform>
formのidは付与されずに生成されます。
<input id="txt" type="text" name="txt">
jQueryと併用する場合
JSFとJavaScript系ライブラリの愛称が良いか悪いかはとりあえず置いておいて…jQueryなど利用する際にJSFで生成されたidを利用してセレクタで引っかけるなどあると思います。
普通に定義すると
何も意識せず定義すると以下のような感じかと。
JSFで定義されたinputTextにjQueryで値を入れてます。
<houtputScript library="js" name="jquery-2.1.0.min.js" />
<hform id="frm">
<hinputText id="txt" />
<script type="text/javascript">
$(document).ready(function(){
$('#frm:txt').val('JSFのIDテスト');
});
</script>
</hform>
実行すると…
表示されない…Firebugでみるとエラーになってます。
jQueryではコロンがセレクタでの予約語になってるためエスケープが必要なのでこうなるようです。
エスケープする
コロンをエスケープします。
<houtputScript library="js" name="jquery-2.1.0.min.js" />
<hform id="frm">
<hinputText id="txt" />
<script type="text/javascript">
$(document).ready(function(){
$('#frm\\:txt').val('JSFのIDテスト');
});
</script>
</hform>
今度はちゃんと動きます。
上記の例は簡単ですが、たくさんある場合はいちいちエスケープするの面倒ですね(^^;
JSFでは連結文字をコロン以外にも変更できるようになっています。
連結文字を変更する
前に書いた以下記事より
JSFで自動生成されるidの区切り文字(コロン)を変える設定
web.xmlにて以下追加します。ハイフンを利用してみます。
<context-param>
<param-name>javax.faces.SEPARATOR_CHAR</param-name>
<param-value>-</param-value>
</context-param>
今度はエスケープせずにハイフンを指定した連結idを指定します。
<houtputScript library="js" name="jquery-2.1.0.min.js" />
<hform id="frm">
<hinputText id="txt" />
<script type="text/javascript">
$(document).ready(function(){
$('#frm-txt').val('JSFのIDテスト');
});
</script>
</hform>
動きます。
生成されたidを確認すると
<input id="frm-txt" type="text" name="frm-txt">
ちゃんとハイフンで連結されてます。
複合コンポーネントの場合
resources配下にkikutaroフォルダ作って、その中に複合コンポーネントのxhtmlを配置します。
以下のようにラベルとテキストを1つにした複合コンポーネントを新たに定義します。
xml version='1.0' encoding='UTF-8'
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlnsh="http://java.sun.com/jsf/html"
xmlnscomposite="http://java.sun.com/jsf/composite">
<compositeinterface>
<compositeattribute name ="labelValue" />
<compositeattribute default="hello!" name ="txtValue" />
</compositeinterface>
<compositeimplementation>
<houtputLabel id="cmpLbl" value="#{cc.attrs.labelValue}" />
<hinputText id="cmpTxt" value="#{cc.attrs.txtValue}" />
</compositeimplementation>
</html>
上記の複合コンポーネントを利用してxhtmlに定義します。
<hform id="frm">
<mylabeltext id="lblTxt" labelValue="ラベルだよ" />
</hform>
生成されたラベル、テキストを確認すると以下のようになります。
formのidと複合コンポーネントのid、そして複合コンポーネントの内部で定義されたidが連結されてます。
<label id="frm:lblTxt:cmpLbl" for="frm:lblTxt:cmpTxt"> ラベルだよ</label>
<input id="frm:lblTxt:cmpTxt" type="text" value="hello!" name="frm:lblTxt:cmpTxt">
意識するケース
PrimeFacesみたいなJSFライブラリ使ってるとAjaxによる部分更新などをupdate属性で指定できるのですが、その際に上記のようなidを指定したりします。
(PrimeFaces自体もjQueryベースのセレクタを内包してるのでそちらも使えますが)
あとはfor属性とか、管理対象Beanでidをキーにコンポーネントオブジェクトを利用する場合とか…。
結構めんどい(^^;
JSFで生成されるhtmlも複雑になると可読性が悪いし、やはりJAX-RS + クライアント側でJavaScriptフレームワークがいいのかなぁ、と思う今日この頃。