如果您需要使用不同于
<p:autoComplete>
的渲染器实现特定组件,那么您真的无法创建具有自己的family和component type的自定义组件。但是,您仍然可以扩展PrimeFaces
AutoComplete
(以及其渲染器)以节省一些样板代码。
在自定义组件中,您需要为这些属性提供getter方法。您也可以指定setter方法,这样您就可以始终从视图端重写默认值。这些getter/setter方法应该将操作委托给
StateHelper
。
只有
x-webkit-*
属性存在一些问题。在Java标识符中,
-
是一个非法字符。因此,您必须重新命名getter/setter方法,并在某种程度上更改渲染器,因为标准渲染器依赖于组件属性名称与标签属性名称完全相同。更新:我了解到
x-webkit-speech
应该按原样呈现(因此,不需要getter/setter方法),而
x-webkit-grammer
实际上是一个拼写错误,应该是
x-webkit-grammar
。
以下是
SiteSearch
组件的示例。
@FacesComponent(SiteSearch.COMPONENT_TYPE)
public class SiteSearch extends AutoComplete {
public static final String COMPONENT_FAMILY = "com.example";
public static final String COMPONENT_TYPE = "com.example.SiteSearch";
private enum PropertyKeys {
grammar, onspeechchange, placeholder
}
@Override
public String getFamily() {
return COMPONENT_FAMILY;
}
@Override
public String getRendererType() {
return SiteSearchRenderer.RENDERER_TYPE;
}
public String getGrammar() {
return (String) getStateHelper().eval(PropertyKeys.grammar, "builtin:search");
}
public void setGrammar(String grammar) {
getStateHelper().put(PropertyKeys.grammar, grammar);
}
public String getOnspeechchange() {
return (String) getStateHelper().eval(PropertyKeys.onspeechchange, "submit()");
}
public void setOnspeechchange(String onspeechchange) {
getStateHelper().put(PropertyKeys.onspeechchange, onspeechchange);
}
public String getPlaceholder() {
return (String) getStateHelper().eval(PropertyKeys.placeholder, "Enter a Search Term");
}
public void setPlaceholder(String placeholder) {
getStateHelper().put(PropertyKeys.placeholder, placeholder);
}
}
请注意,所有getter都指定了默认值。如果
eval()
返回
null
,则将返回默认值。我还使属性名称有些中性化,这样只需相应地修改渲染器即可在未来的非webkit浏览器中重用它。
以下是上述组件所需的
SiteSearchRenderer
渲染器的外观:
@FacesRenderer(
componentFamily=SiteSearch.COMPONENT_FAMILY,
rendererType=SiteSearchRenderer.RENDERER_TYPE
)
public class SiteSearchRenderer extends AutoCompleteRenderer {
public static final String RENDERER_TYPE = "com.example.SiteSearchRenderer";
@Override
protected void renderPassThruAttributes(FacesContext facesContext, UIComponent component, String[] attrs) throws IOException {
ResponseWriter writer = facesContext.getResponseWriter();
writer.writeAttribute("x-webkit-speech", "x-webkit-speech", null);
writer.writeAttribute("x-webkit-grammar", component.getAttributes().get("grammar"), "grammar");
writer.writeAttribute("onwebkitspeechchange", component.getAttributes().get("onspeechchange"), "onspeechchange");
writer.writeAttribute("placeholder", component.getAttributes().get("placeholder"), "placeholder");
super.renderPassThruAttributes(facesContext, component, attrs);
}
}
为在视图中使用它,我们当然需要将它作为标签进行注册。创建一个/WEB-INF/my.taglib.xml
文件:
<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib
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-facelettaglibrary_2_0.xsd"
version="2.0"
>
<namespace>http://example.com/ui</namespace>
<tag>
<tag-name>siteSearch</tag-name>
<component>
<component-type>com.example.SiteSearch</component-type>
<renderer-type>com.example.SiteSearchRenderer</renderer-type>
</component>
</tag>
</facelet-taglib>
请注意,您不再需要在
faces-config.xml
中使用
<renderer>
了。现在
@FacesRenderer
注释可以在真正的自定义组件上发挥作用。因此,请从
faces-config.xml
中删除您根据先前问题创建的
<renderer>
条目。
现在,请通过以下方式在
web.xml
中设置上下文参数,以告知JSF您拥有一个自定义标签库:
<context-param>
<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
<param-value>/WEB-INF/my.taglib.xml</param-value>
</context-param>
最后,您可以按如下方式使用它:
<html ... xmlns:my="http://example.com/ui">
...
<my:siteSearch />
你甚至可以指定其他属性,这些属性将覆盖组件中设置的默认值:
<my:siteSearch grammar="builtin:language" onspeechchange="alert('peek-a-boo')" placeholder="Search" />
为了在IDE中自动补全属性,您需要将每个属性单独指定为<tag>
声明中的<attribute>
。在my.taglib.xml
中。