私が見つけた解決策は、入力レンダラーの encodeMarkup メソッドを拡張して再実装することでした。もっと一般的な解決策が欲しかったのですが、Primefaces のソース コードを調べたところ、コンポーネント レンダラーがカスタム属性を追加するための一般的なフックが見つかりませんでした。encodeMarkup(FacesContext context, InputText inputText)
マークアップは、レンダラーのメソッドで書き出されます。へのクラス階層を呼び出しますがrenderPassThruAttributes(FacesContext context, UIComponent component, String[] attributes)
、からの static final String[] 配列のみをフィードしますorg.primefaces.util.HTML
。
私の場合、InputMask、InputText、InputTextarea、および Password コンポーネントの「autofocus」属性のサポートが必要でした。さらに、各コンポーネントの実装は同じであるため、InputText コンポーネントに「オートフォーカス」を実装する方法について説明しますが、より多くの属性とコンポーネントをサポートするために拡張する方法は明らかです。
レンダラーを拡張/オーバーライドするには、Primefaces ソースを利用可能にし、encodeMarkup メソッドを見つけてその内容をコピーする必要があります。以下は、InputTextRenderer の例です。
protected void encodeMarkup(FacesContext context, InputText inputText) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String clientId = inputText.getClientId(context);
writer.startElement("input", null);
writer.writeAttribute("id", clientId, null);
writer.writeAttribute("name", clientId, null);
writer.writeAttribute("type", inputText.getType(), null);
String valueToRender = ComponentUtils.getValueToRender(context, inputText);
if(valueToRender != null) {
writer.writeAttribute("value", valueToRender , null);
}
renderPassThruAttributes(context, inputText, HTML.INPUT_TEXT_ATTRS);
if(inputText.isDisabled()) writer.writeAttribute("disabled", "disabled", null);
if(inputText.isReadonly()) writer.writeAttribute("readonly", "readonly", null);
if(inputText.getStyle() != null) writer.writeAttribute("style", inputText.getStyle(), null);
writer.writeAttribute("class", createStyleClass(inputText), "styleClass");
writer.endElement("input");
}
独自のレンダラーを拡張/オーバーライドする (重要なコードについてはコメントを参照してください):
public class HTML5InputTextRenderer extends InputTextRenderer {
Logger log = Logger.getLogger(HTML5InputTextRenderer.class);
//Define your attributes to support here
private static final String[] html5_attributes = { "autofocus" };
protected void encodeMarkup(FacesContext context, InputText inputText) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String clientId = inputText.getClientId(context);
writer.startElement("input", null);
writer.writeAttribute("id", clientId, null);
writer.writeAttribute("name", clientId, null);
writer.writeAttribute("type", inputText.getType(), null);
String valueToRender = ComponentUtils.getValueToRender(context, inputText);
if (valueToRender != null) {
writer.writeAttribute("value", valueToRender, null);
}
renderPassThruAttributes(context, inputText, HTML.INPUT_TEXT_ATTRS);
//Make an extra call to renderPassThruAttributes with your own attributes array
renderPassThruAttributes(context, inputText, html5_attributes);
if (inputText.isDisabled())
writer.writeAttribute("disabled", "disabled", null);
if (inputText.isReadonly())
writer.writeAttribute("readonly", "readonly", null);
if (inputText.getStyle() != null)
writer.writeAttribute("style", inputText.getStyle(), null);
writer.writeAttribute("class", createStyleClass(inputText), "styleClass");
writer.endElement("input");
}
}
faces-config.xml でのレンダリング オーバーライドの構成
<?xml version='1.0' encoding='UTF-8'?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<!-- snip... -->
<render-kit>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.InputTextRenderer</renderer-type>
<renderer-class>com.mycompany.HTML5InputTextRenderer</renderer-class>
</renderer>
</render-kit>
<!-- snip... -->
</faces-config>
念のため、web.xml で faces-config を構成していない場合は、次のように追加します。
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>
/WEB-INF/faces-config.xml, /faces-config.xml
</param-value>
</context-param>
次に、これをマークアップで使用するには:
<p:inputText id="activateUserName" value="${someBean.userName}"
autofocus="on">
</p:inputText>
注: JSF は、値を持たない属性に満足していません。HTML5 の autofocus は値を使用しませんが、JSF は値が指定されていないとエラーをスローするため、そのような属性を追加するときは必ず破棄値を定義してください。