2012-05-13 12 views
5

different questionのパススルー属性について質問しましたが、<p:autocomplete>コンポーネント用のカスタムレンダラーを作成できましたが、私のカスタムレンダラーはすべてのp:オートコンプリートに使用されますプロジェクト(サイト全体)。したがって、私はorg.primefaces.component.autocomplete.AutoCompleteを拡張し、必要な属性をテキストボックスに追加するカスタムコンポーネントを作成することに決めました。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に拡張されたカスタムレンダラーを指定し、そこで属性を変更します。

これらの属性をこの1つのテキストボックスに分けて、p:autoCompleteにカスタムレンダラーを置くだけの方法は必要です(renderType =この1つの属性:autoComplete?)。

+0

@BalusCどのようなアイデアですか? – Adam

+0

シリーズを見ていました(現在、House MDです)。少しの忍耐をしてください:) – BalusC

+0

ハハ。問題ではない。 JSFの質問が表示されるたびに、私は自動的にあなたのことが見えなくても答えになると思います。誰もJSF忍者と言うことができますか? – Adam

答えて

18

<p:autoComplete>以外のレンダラーを使用する特定のコンポーネントが必要な場合は、独自のファミリとコンポーネントタイプを持つカスタムコンポーネントを作成することはできません。ボイラープレートのコードを保存するためにPrimeFaces AutoComplete(およびそのレンダラ)を拡張することもできます。

カスタムコンポーネントでは、これらの属性にゲッターを指定する必要があります。 setterも同様に指定することができます。この方法では、ビュー側からデフォルト値をオーバーライドできます。これらのゲッター/セッターは、StateHelperに委任する必要があります。

属性がx-webkit-*の場合、少し問題があります。 -はJava識別子では不正な文字です。したがって、標準のレンダラーは、タグ属性名とまったく同じコンポーネントプロパティ名に依存するため、getters/setterの名前を変更してレンダラーを多少変更する必要があります。 更新x-webkit-speechはそのままレンダリングする必要があり(ゲッター/セッターは必要ありません)、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); 
    } 

} 

ビューでそれを使用するには、当然の我々は、タグとして登録する必要があります。あなたはもうこのためfaces-config.xml<renderer>を必要としない

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

注:/WEB-INF/my.taglib.xmlファイルを作成します。 @FacesRendererアノテーションは、実際のカスタムコンポーネントでその作業を行うことができます。したがって、あなたの前の質問に基づいて作成したの<renderer>エントリを削除してください。

今、あなたはweb.xmlで、次のコンテキストのparamしてカスタムタグライブラリを持っていること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<tag>宣言には、それぞれを別々の<attribute>として指定する必要があります。

+0

うわー。あなたはロック!ありがとう! – Adam

+0

ようこそ。 – BalusC

+0

@BalusC、私のカスタムコンポーネントでこれを実現するには、どのようにcompoisteを使って作成したかhttps://stackoverflow.com/questions/44454804/composite-attributes-returns-null-in-jsf-custom-components –