我正在构建一个定制的UIComponent,并在其中添加元素(和其他股票UIComponents)。组件呈现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" />这呈现ok,但是我无法从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?当我尝试添加其他UIComponents作为自定义组件的子组件时,也会出现同样的问题--它们会成功地呈现,但是无法从组件树中找到,因为我的自定义组件本身并不驻留在那里。
将组件放入组件树的诀窍是什么?
编辑:调整标题以更好地反映问题。
发布于 2010-11-25 09:53:30
这是一个愚蠢的错误造成的。正如人们所设想的,添加的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中的,但是它内部的UIEditPanel没有,因为我只是在调用encodeAll(context),所以UIEditPanel无法知道它的父级。一个快速的解决方法是手动设置子组件的父组件:
editor.setParent(this);另一种方法(也许更好)是从UIComponentBase扩展(像我们通常所做的那样),而不是手动调用encodeAll(context),而只是将组件作为一个子组件添加到encodeBegin(...)中,而不是在encodeAll(...)中。
@Override
public void encodeBegin(FacesContext context) throws IOException {
UIEditPanel editor = new UIEditPanel();
getChildren().add(editor);
}getChildren().add()内部将当前组件添加为子组件的父级。
考虑到子创建的位置,最好是直接在构造函数中构建它们,而根本不覆盖encodeXXX方法,如果不需要使用ResponseWriter (如果有,那么就需要覆盖这些方法)。但是,无论您需要什么,重写和手动调用编码都更灵活。
还请注意,自定义UIComponent不能直接成为<f:ajax render=目标,因为它不是由DOM树中的DOM元素表示的。这与复合组件的情况是一样的,在这种情况下,我倾向于将复合组件实现封装到JSFManagedpanelGroup中,以便稍后可以重新呈现内容。
发布于 2010-11-24 15:47:29
我不确定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);将只在ID生成的组件上设置<div id="myForm:myComponent:testDiv">属性(即将页面中的<div id="myForm:myComponent:testDiv">发送给浏览器)。这个<div>组件在您的JSF树中不存在,因此无法在Java端检索。
https://stackoverflow.com/questions/4268546
复制相似问题