JSF2.0:如何将UIComponents及其内容添加到ViewRoot?

JSF2.0:如何将UIComponents及其内容添加到ViewRoot?,jsf,jsf-2,uicomponents,Jsf,Jsf 2,Uicomponents,我正在构建一个自定义UIComponent,并在其中添加元素和其他库存UIComponent。组件呈现为ok,但无法从ViewRoot中找到它 假设我有: ResponseWriter writer; @Override public void encodeBegin(FacesContext context) throws IOException { writer = context.getResponseWriter(); writer.startElement("div"

我正在构建一个自定义UIComponent,并在其中添加元素和其他库存UIComponent。组件呈现为ok,但无法从ViewRoot中找到它

假设我有:

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");        
}
加上:

<x:myUiComponent id="myComponent" />
当我尝试添加其他UIComponent作为自定义组件的子组件时,同样的问题也会出现——它们成功渲染,但是无法从组件树中找到,因为自定义组件本身不在其中

将组件放入组件树的诀窍是什么

编辑:调整标题以更好地反映问题。

我不确定GetClientContext是否会返回myComponent。事实上,如果您的组件嵌套在一个组件中,例如a,那么他的ID将以该容器的ID作为前缀

例如,如果您有以下XHTML页面:

<h:form id="myForm">
    <x:myUiComponent id="myComponent" />
关于context.getViewRoot.findComponentmyComponent:testDiv;或context.getViewRoot.findComponentmyForm:myComponent:testDiv;,它将返回null,因为在服务器端的JSF组件树中没有这样的元素。守则:

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

将只在HTML生成的组件上设置ID属性,即您将在HTML页面中有一个ID发送到浏览器。此组件在JSF组件树中不存在,因此无法在Java端检索。

这是由一个愚蠢的错误造成的。正如人们所想,添加的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 />
另一种更好的方法可能是像我们通常所做的那样从UIComponentBase进行扩展,而不是手动调用encodeAllcontext,而是将组件作为子组件添加到getChildren.add。。。在开始时。。。而不是所有…:

getChildren.add在内部将当前组件添加为子组件的父组件

考虑到子创建的位置,最好直接在构造函数中构建它们,而不重写encodeXXX方法,如果不需要使用ResponseWriter,那么您需要重写这些方法。但是,无论您需要什么,重写和手动调用编码都更为灵活


还请注意,自定义UIComponent不能直接是Mmmm,您是对的,在本例中,getClientContext实际上返回JSF生成的ID j_id11。我想必须通过setId用UIComponents手动覆盖自动生成的ID。在这种情况下,生成的ID没有前缀,因为我直接从h:body调用组件。无论如何,如何添加自定义UIComponent,使其本身添加到组件树中,例如,通过AJAX调用重新渲染它?如果不可能,我如何在UIComponent中添加子元素,以便将它们添加到组件树中?好的,谢谢您的输入,我发现了问题,请参阅我的答案。我想这甚至是从问题中看不出来的。下次我会更加小心的!
@Override
public void encodeAll(FacesContext context) throws IOException {
    UIEditPanel editor = new UIEditPanel();
    editor.encodeAll(context);
}
<!-- codeEditor is taghandler for UICodeEditor -->
<x:codeEditor />
editor.setParent(this);
@Override
public void encodeBegin(FacesContext context) throws IOException {
    UIEditPanel editor = new UIEditPanel();
    getChildren().add(editor);
}