2010-11-24 7 views
2

私はカスタムUIComponentを構築しており、その中に要素(および他のストックUIComponent)を追加しています。コンポーネントは表示されますが、ViewRootからは見つかりません。することを追加JSF 2.0:UIComponentとその内容を追加してルートを表示する方法は?

ResponseWriter writer; 

@Override 
public void encodeBegin(FacesContext context) throws IOException { 
    writer = context.getResponseWriter(); 
    writer.startElement("div", this); 
    writer.writeText("testing", null); 
    writer.writeAttribute("id", getClientId(context) + ":testDiv", null); 
} 

@Override 
public void encodeEnd(FacesContext context) throws IOException { 
    writer.endElement("div");   
} 

::これはOKレンダリング

<x:myUiComponent id="myComponent" /> 

、しかし私はコンポーネントを見つけることができないか、それがViewRootから、子のdivです:

context.getViewRoot().findComponent("myComponent"); // returns null 
context.getViewRoot().findComponent("myComponent:testDiv"); // returns null 
findComponent("myComponent:testDiv"); // called within the custom component, throws java.lang.IllegalArgumentException? 

のは、私が持っているとしましょう

他のUIComponentをカスタムコンポーネントの子として追加しようとすると、同じ問題が発生します私のカスタムコンポーネント自体は存在しないので、コンポーネントツリーからは見つかりません。

ここでコンポーネントをコンポーネントツリーに入れるにはどのようなトリックですか?

:質問をよく反映するようにタイトルを調整しました。

答えて

1

これは愚かな間違いのために発生しました。予想通り、UIComponentに自動的に追加され、ViewRootに追加されます。私は他のカスタムUIComponent(これはそこにあることを忘れていたので言及していません)の中からカスタムUIComponent(質問で話していたもの)を呼び出しました:

UICodeEditor:

@Override 
public void encodeAll(FacesContext context) throws IOException { 
    UIEditPanel editor = new UIEditPanel(); 
    editor.encodeAll(context); 
} 

はその後のようなテンプレートでこれを呼ばれる:

ここ
<!-- codeEditor is taghandler for UICodeEditor --> 
<x:codeEditor /> 

、UICodeEditor は自動的ViewRoot、しかし、UIEditPaneにを追加取得ん私は単にencodeAll(context)と呼んでいたので、UIEditPanelはその親を知る方法がありません。 UIComponentBaseから延びる(私たちは通常どおり)ではなく、手動でencodeAll(context)を呼び出すが、ただのコンポーネントを追加することです(おそらくより良い)

editor.setParent(this); 

代替アプローチ:クイックフィックスは、手動で子コンポーネントの親を設定することですencodeBegin(...)ではないencodeAll(...)getChildren.add(...)との子として:

@Override 
public void encodeBegin(FacesContext context) throws IOException { 
    UIEditPanel editor = new UIEditPanel(); 
    getChildren().add(editor); 
} 

getChildren().add()は、内部的に子供の親として現在のコンポーネントを追加します。

ResponseWriterを使用する必要がない場合は、子の作成場所を考慮して、コンストラクタで直接作成し、encodeXXXメソッドをオーバーライドしない方がよい場合があります(存在する場合は、 )。ただし、必要に応じて、エンコードをオーバーライドして手動で呼び出すほうが柔軟性があります。

また、カスタムUIComponentは、<f:ajax render=ターゲットではありません.DOMツリーのDOM要素では表現されないためです。これはコンポジット・コンポーネントの場合と同じですが、コンポジット・コンポーネントの実装をJSF管理のpanelGroupにラップして、コンテンツを後で再レンダリングできるようにする傾向があります。

4

getClientId(context)myComponentを返すかどうかはわかりません。実際に、コンポーネントがNamingContainerコンポーネントにネストされている場合(<h:form>など)、そのIDにはこのコンテナのIDの接頭辞が付きます。

次のXHTMLページがある場合たとえば、:

<h:form id="myForm"> 
    <x:myUiComponent id="myComponent" /> 

を、あなたが使用してコンポーネントを取得する必要がありますが:

context.getViewRoot().findComponent("myForm:myComponent"); 

context.getViewRoot().findComponent("myComponent:testDiv");(またはcontext.getViewRoot().findComponent("myForm:myComponent:testDiv");に関しては、 nullはそのような要素がないため返されますJSFコンポーネントツリーサーバー側。コード:

writer.writeAttribute("id", getClientId(context) + ":testDiv", null); 

だけHTML上のID属性はコンポーネントを生成しますが、あなたがブラウザに送信されたHTMLページに<div id="myForm:myComponent:testDiv">を持つことになりますすなわち。この<div>コンポーネントは、JSFコンポーネントツリーに存在しないため、Java側では取得できません。

+0

実際、getClientId(context)はJSF生成ID(この場合は "j_id11")を返します。 UIComponentsで(setId()経由で)自動的に生成されたIDを手動でオーバーライドする必要があると思います。生成されたIDには、この場合は接頭辞がありません。私は 'h:body'から直接コンポーネントを呼び出します。とにかく、カスタムUIComponentを追加して、それ自体がコンポーネントツリーに追加されるようにするにはどうすればいいですか?(たとえば、AJAX呼び出しで再レンダリングできるように)それが不可能な場合、UIComponent内のサブ要素を追加してコンポーネントツリーに追加するにはどうすればよいですか? –

+0

あなたのご意見ありがとう、私は問題を見つけました(私の答えを見てください)。私はこれが質問から見えないものであったと思う。私は次回より注意しようとします! –

関連する問題