我找到的解决方案是扩展和重新实现输入渲染器的 encodeMarkup 方法。我想要一个更通用的解决方案,但是在查看 Primefaces 源代码后,我没有看到任何用于组件渲染器添加自定义属性的通用挂钩。标记写在encodeMarkup(FacesContext context, InputText inputText)
渲染器的方法中。它调用类层次结构,renderPassThruAttributes(FacesContext context, UIComponent component, String[] attributes)
但它只从org.primefaces.util.HTML
.
就我而言,我希望支持 InputMask、InputText、InputTextarea 和 Password 组件上的“自动对焦”属性。此外,每个组件的实现都是相同的,因此我将介绍如何在 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 会抛出错误,因此在添加此类属性时请务必定义一些丢弃值。