Challenge Engineer Life !

エンジニア人生を楽しみたい!仕事や趣味で学んだ技術的なことを書いていくブログです。

JSFで生成されるidあれこれ

先日以下@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"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>例題に合わせて変更</title>
    </h:head>
    <h:body>
        <!-- 以降ここの定義を抜粋 -->
    </h:body>
</html>

id属性を指定しない場合

formにもinputTextにもid属性を付与せずに定義。

<h:form>
    <h:inputText />
</h:form>

レンダリングされたxhtmlからテキスト部分だけを抜いてみると

<input type="text" name="j_idt7:j_idt8">

idはなく、適当に(数字は全体におけるタグの番号?)付番されたnameがついてます。

id属性を指定した場合

formとinputTextにid属性を指定します。

<h:form id="frm">
   <h:inputText id="txt"/>
</h:form>

結果、コロンでformのidとtextのidが連結されて生成されています。

<input id="frm:txt" type="text" name="frm:txt">

FormタグのprependIdをfalseにした場合

formのidを連結しなくていいんだけど…という場合にはformタグのprependId属性をfalseにすると

<h:form id="frm" prependId="false">
    <h:inputText id="txt"/>
</h:form>

formのidは付与されずに生成されます。

<input id="txt" type="text" name="txt">

jQueryと併用する場合

JSFとJavaScript系ライブラリの愛称が良いか悪いかはとりあえず置いておいて…jQueryなど利用する際にJSFで生成されたidを利用してセレクタで引っかけるなどあると思います。

普通に定義すると

何も意識せず定義すると以下のような感じかと。
JSFで定義されたinputTextにjQueryで値を入れてます。

<h:outputScript library="js" name="jquery-2.1.0.min.js" />
<h:form id="frm">
    <h:inputText id="txt" />
        
    <script type="text/javascript">
        $(document).ready(function(){
            $('#frm:txt').val('JSFのIDテスト');
        });
    </script>
</h:form>

実行すると…

f:id:kikutaro777:20140502183928j:plain

表示されない…Firebugでみるとエラーになってます。

f:id:kikutaro777:20140502183947j:plain

jQueryではコロンがセレクタでの予約語になってるためエスケープが必要なのでこうなるようです。

エスケープする

コロンをエスケープします。

<h:outputScript library="js" name="jquery-2.1.0.min.js" />
<h:form id="frm">
    <h:inputText id="txt" />
        
    <script type="text/javascript">
        $(document).ready(function(){
            $('#frm\\:txt').val('JSFのIDテスト');
        });
    </script>
</h:form>

今度はちゃんと動きます。

f:id:kikutaro777:20140502190313j:plain

上記の例は簡単ですが、たくさんある場合はいちいちエスケープするの面倒ですね(^^;

JSFでは連結文字をコロン以外にも変更できるようになっています。

連結文字を変更する

前に書いた以下記事より

JSFで自動生成されるidの区切り文字(コロン)を変える設定

web.xmlにて以下追加します。ハイフンを利用してみます。

<context-param>
    <param-name>javax.faces.SEPARATOR_CHAR</param-name>
    <param-value>-</param-value>
</context-param>

今度はエスケープせずにハイフンを指定した連結idを指定します。

<h:outputScript library="js" name="jquery-2.1.0.min.js" />
<h:form id="frm">
    <h:inputText id="txt" />
        
    <script type="text/javascript">
        $(document).ready(function(){
            $('#frm-txt').val('JSFのIDテスト');
        });
    </script>
</h:form>

動きます。

f:id:kikutaro777:20140502184738j:plain

生成されたidを確認すると

<input id="frm-txt" type="text" name="frm-txt">

ちゃんとハイフンで連結されてます。

複合コンポーネントの場合

resources配下にkikutaroフォルダ作って、その中に複合コンポーネントのxhtmlを配置します。
f:id:kikutaro777:20140502182413j:plain

以下のようにラベルとテキストを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"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:composite="http://java.sun.com/jsf/composite">

    <composite:interface>
        <composite:attribute name ="labelValue" />
        <composite:attribute default="hello!" name ="txtValue" />
    </composite:interface>
    
    <composite:implementation>
        <h:outputLabel id="cmpLbl" value="#{cc.attrs.labelValue}" />
        <h:inputText id="cmpTxt" value="#{cc.attrs.txtValue}" />
    </composite:implementation>
</html>

上記の複合コンポーネントを利用してxhtmlに定義します。

<h:form id="frm">
    <my:labeltext id="lblTxt" labelValue="ラベルだよ" />
</h:form>

生成されたラベル、テキストを確認すると以下のようになります。

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フレームワークがいいのかなぁ、と思う今日この頃。

にほんブログ村 IT技術ブログへ
にほんブログ村 にほんブログ村 IT技術ブログ Javaへ
にほんブログ村