2012-05-13 86 views
5

我詢問了關於穿過different question中的屬性並發現我可以爲<p:autocomplete>組件創建自定義渲染器,但問題是我的自定義渲染器將用於每個p:autocomplete在我的項目(整個網站)。因此,我選擇創建一個自定義組件,它將擴展org.primefaces.component.autocomplete.AutoComplete並將必要的屬性添加到文本框中。將自定義屬性添加到Primefaces自動完成組件在JSF中

我最初的想法是,添加一個構造函數,但它似乎並沒有工作,因爲屬性地圖在這一點空:

@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?)。

+0

@BalusC有什麼想法? – Adam

+0

正在觀看系列(現在的房子MD)。有一點耐心:) – BalusC

+0

哈哈。沒有問題。我想,只要我看到一個JSF問題,我就會自動假設你的答案沒有看到。任何人都可以說JSF忍者? – Adam

回答

18

如果您需要使用與<p:autoComplete>不同的渲染器的特定組件,那麼您實際上無法繞過使用其自己的族和組件類型創建自定義組件。您仍然可以擴展PrimeFaces AutoComplete(及其渲染器)以保存一些樣板代碼。

在自定義組件中,您需要爲這些屬性提供獲取者。你也可以很好的指定setter,這樣你總是可以覆蓋視圖中的默認值。那些獲得者/安排者應該依次代表StateHelper

x-webkit-*屬性只有一個小問題。 -是Java標識符中的非法字符。因此,您必須重新命名getter/setters並更改渲染器,因爲標準渲染器依賴於組件屬性名稱與標記屬性名稱完全相同。 更新:據我所知,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); 
    } 

} 

請注意,干將有指定的所有默認值。如果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>條目。

現在告訴JSF,你有通過以下方面PARAM自定義標籤庫中web.xml

<html ... xmlns:my="http://example.com/ui"> 
... 
<my:siteSearch /> 

你甚至可以指定其他:

<context-param> 
    <param-name>javax.faces.FACELETS_LIBRARIES</param-name> 
    <param-value>/WEB-INF/my.taglib.xml</param-value> 
</context-param> 

最後,您可以按如下方式使用它將覆蓋組件中默認設置的屬性:

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

對於屬性上的IDE自動完成,您需要在my.taglib.xml<tag>聲明中指定每一個爲單獨的<attribute>

+0

哇。你搖滾!謝謝! – Adam

+0

不客氣。 – BalusC

+0

@BalusC,如何爲我的自定義組件實現這一點,它使用compoiste創建,如給定的https://stackoverflow.com/questions/44454804/composite-attributes-returns-null-in-jsf-custom-components –

相關問題