将自定义属性添加到JSF中的Primefaces自动完成组件

时间:2012-05-13 01:12:45

标签: jsf jsf-2 primefaces custom-component

我询问different question中的传递属性,发现我可以为<p:autocomplete>组件创建自定义渲染器,但问题是我的自定义渲染器将用于我项目中的每个p:autocomplete (站点范围)。因此,我选择创建一个扩展org.primefaces.component.autocomplete.AutoComplete的自定义组件,并将必要的属性添加到文本框中。

我最初的想法是添加一个构造函数,但它似乎不起作用,因为此时属性map为null:

@FacesComponent("com.mycomponents.SiteSearch")
public class SiteSearch extends AutoComplete {

    public SiteSearch() {
        Map<String,Object> attrs = getAttributes();
        attrs.put("x-webkit-speech", null); 
        attrs.put("x-webkit-grammer", "builtin:search");
        attrs.put("onwebkitspeechchange", "this.form.submit();");
        attrs.put("placeholder", "Enter a Search Term");
    }   
}

我的另一个想法是将此自定义组件留空(空类),然后指定扩展org.primefaces.component.autocomplete.AutoCompleteRenderer的自定义渲染器并修改其中的属性。

毕竟说完了之后,我只需要一种方法将这些属性与这一个文本框分开,这样只需在p:autoComplete上放一个自定义渲染器就行不通了(除非我可以使用renderType = attribute对于这一个p:autoComplete?)。

1 个答案:

答案 0 :(得分:18)

如果您需要使用与<p:autoComplete>不同的渲染器的特定组件,那么您实际上无法创建具有自己的族和组件类型的自定义组件。您仍然可以扩展PrimeFaces AutoComplete(及其渲染器)以保存一些样板代码。

在自定义组件中,您需要为这些属性提供getter。你也可以很好地指定setter,这样你总是可以覆盖视图端的默认值。那些getter / setter应该委托给StateHelper

x-webkit-*属性只有一点问题。 -是Java标识符中的非法字符。因此,您必须重命名getter / setter并稍微更改渲染器,因为标准渲染器依赖于组件属性名称与标记属性名称完全相同。 更新:我了解x-webkit-speech应该按原样呈现(因此,不需要getter / setter)并且x-webkit-grammer实际上是一个拼写错误,它应该是{{1} }}

以下是x-webkit-grammar组件的外观:

SiteSearch

请注意,getter具有指定的所有默认值。如果@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); } } 返回eval(),则会返回默认值。我还稍微中了一下属性名称,以便只需相应地修改渲染器就可以将它重用于任何未来的非webkit浏览器。

以下是上述组件的null渲染器的外观:

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> 中不再需要<renderer>faces-config.xml注释可以在真实的自定义组件上完成它的工作。因此,请根据您之前的问题删除您创建的@FacesRenderer中的<renderer>条目。

现在告诉JSF你已经通过faces-config.xml中的以下上下文参数获得了自定义taglib:

web.xml

最后你可以按如下方式使用它:

<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 />

对于属性的IDE自动填充,您需要在<my:siteSearch grammar="builtin:language" onspeechchange="alert('peek-a-boo')" placeholder="Search" /> 的{​​{1}}声明中将每个属性指定为单独的<attribute>