【问题标题】:Adding Custom Attributes to Primefaces Autocomplete Component in JSF在 JSF 中向 Primefaces 自动完成组件添加自定义属性
【发布时间】:2012-05-21 01:40:36
【问题描述】:

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

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

@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= 属性对于这个 p:autoComplete?)。

【问题讨论】:

  • 正在看连续剧(现在是 House MD)。有一点耐心:)
  • 哈哈。不是问题。我想每当我看到一个 JSF 问题时,我都会自动假设你的问题将是答案,甚至不用看。谁能说JSF忍者?

标签: jsf jsf-2 primefaces custom-component


【解决方案1】:

如果您需要一个使用与&lt;p:autoComplete&gt; 不同的渲染器的特定组件,那么您真的无法创建具有自己的系列和组件类型的自定义组件。您仍然可以扩展 PrimeFaces AutoComplete(及其渲染器)以节省一些样板代码。

在自定义组件中,您需要为这些属性提供 getter。您也可以指定设置器,这样您就可以始终覆盖视图端的默认值。这些 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 中添加&lt;renderer&gt;@FacesRenderer 注释可以在真正的自定义组件上完成它的工作。因此,请删除您根据之前的问题创建的 faces-config.xml 中的 &lt;renderer&gt; 条目。

现在通过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 自动完成,您需要在 my.taglib.xml&lt;tag&gt; 声明中将每个属性指定为单独的 &lt;attribute&gt;

【讨论】:

猜你喜欢
  • 2017-11-07
  • 2011-10-15
  • 2013-03-12
  • 1970-01-01
  • 2021-12-05
  • 2015-01-02
  • 1970-01-01
  • 1970-01-01
  • 2011-03-12
相关资源
最近更新 更多