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

Ada*_*dam 6 jsf custom-component primefaces jsf-2

我在一个不同的问题中询问了传递属性,发现我可以为<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");
    }   
}
Run Code Online (Sandbox Code Playgroud)

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

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

Bal*_*usC 18

如果您需要使用不同渲染器的特定组件,<p:autoComplete>那么您实际上无法创建具有自己的族和组件类型的自定义组件.您仍然可以扩展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);
    }

}
Run Code Online (Sandbox Code Playgroud)

请注意,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);
    }

}
Run Code Online (Sandbox Code Playgroud)

要在视图中使用它,我们当然需要将其注册为标记.创建一个/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>
Run Code Online (Sandbox Code Playgroud)

请注意,您不再需要<renderer>in faces-config.xml.该@FacesRenderer注释可以做真实的自定义组件的工作.因此,请根据您之前的问题删除您创建的<renderer>条目faces-config.xml.

现在告诉JSF您通过以下上下文参数获得了自定义taglib web.xml:

<context-param>
    <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
    <param-value>/WEB-INF/my.taglib.xml</param-value>
</context-param>
Run Code Online (Sandbox Code Playgroud)

最后你可以使用它如下:

<html ... xmlns:my="http://example.com/ui">
...
<my:siteSearch />
Run Code Online (Sandbox Code Playgroud)

您甚至可以指定其他属性,这些属性将覆盖组件中设置的默认值:

<my:siteSearch grammar="builtin:language" onspeechchange="alert('peek-a-boo')" placeholder="Search" />
Run Code Online (Sandbox Code Playgroud)

对于属性上的IDE自动完成,您需要<attribute><tag>声明中将每个指定为单独的my.taglib.xml.