JavaEE 7 HTML5に対応したJSF 2.2

JSF 2.2はHTML5に対応したのもポイントになっています。
というか、柔軟性はかなり意識してきていますね。

HTML5ではフォーカスの設定やプレースホルダ、カスタムデータ属性など属性による設定が柔軟に使える必要があります。

そして今後もおそらく属性はどんどん追加されていきますが、そのすべての設定をJSFがサポートするのは骨が折れます。というか、きりがありません。

というわけで、JSF2.2は属性を簡単に設定できるようになりました。

まず基本

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:jsf="http://xmlns.jcp.org/jsf"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:p="http://xmlns.jcp.org/jsf/passthrough">
〜省略〜
<form jsf:id="form">
  <input type="text" jsf:id="input1" p:placeholder="名前を入力してください"/>
</form>

「p:」の後ろにある文字列がそのまま属性として設定されます。


生成されるHTMLは以下のようになります。

<input id="form:input1" name="form:input1" placeholder="名前を入力してください" type="text" />

もちろんバリューバインディングしてもかまいません。

  <input type="text" jsf:id="input1" p:placeholder="#{hoge.attr}"/>
public class Hoge {
  public String getAttr(){
    return "名前を入力してください";
  }
}

属性名も動的に

定型のものはこれでいいのですが、属性の名前はこれでは変更できませんね。バリューバインディングできませんので。

というわけで2つ目の方法です。

<input type="text" jsf:id="input2">
  <f:passThroughAttribute name="placeholder" value="名前を入力してください"/>
  <f:passThroughAttribute name="data-hoge" value="カスタムな値"/>
</input>

f:passThroughAttributeタグを使います。複数ここに並べることができます。

出力結果はこれ。

<input id="form:input2" type="text" placeholder="名前を入力してください"
  data-hoge="カスタムな値" name="form:input2"/>

2つの属性が追加されていますね。

可変の数の属性設定

名前と値を設定できるようになりました。では、属性の数自体が可変の場合はどうしましょうか。

以下のように記述します。

<input type="text" jsf:id="input3">
  <f:passThroughAttributes value="#{hoge.attrs}"/>
</input>
public class Hoge {
    public Map<String,String> getAttrs(){
        HashMap<String, String> attrs = new HashMap<>();
        attrs.put("placeholder", "名前を入力してください");
        attrs.put("autofocus", "true");
        
        return attrs;
    }
}

ちなみにELが拡張されていますので割と自由に書けます。将来はコードでわたすようにするとしてもプロトタイプ的なのはうめこんでおいたほうがいいかもしれません。このようにも書けます。

<input type="text" jsf:id="input4">
    <f:passThroughAttributes value='#{{"placeholder":"名前を入力してください", "data-foo":"bar"}}'/>
</input>

コンポーネントバインディングも対応

コンポーネントバインディングも対応しています。

<input type="text" jsf:id="input5" jsf:binding="#{hoge.compo}"/>
UIInput compo = new UIInput();//フィールド
//コンストラクタ
public Hoge() {
    compo.getPassThroughAttributes().put("placeholder", "名前を入力してください");
}
    
public UIInput getCompo() {
    return compo;
}


最近はJavascriptフレームワークなどでカスタムデータ属性などを使うことも増えたと思います。それに対応できているのがわかりますね。
JavascriptJSFの相性がいいとは思いませんが。