首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JSF2.0:如何将UIComponents及其内容添加到查看根?

JSF2.0:如何将UIComponents及其内容添加到查看根?
EN

Stack Overflow用户
提问于 2010-11-24 15:36:12
回答 2查看 9.5K关注 0票数 2

我正在构建一个定制的UIComponent,并在其中添加元素(和其他股票UIComponents)。组件呈现ok,但是在ViewRoot中找不到它。

假设我有:

代码语言:javascript
复制
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");        
}

补充如下:

代码语言:javascript
复制
<x:myUiComponent id="myComponent" />

这呈现ok,但是我无法从ViewRoot中找到组件或它的子div:

代码语言:javascript
复制
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作为自定义组件的子组件时,也会出现同样的问题--它们会成功地呈现,但是无法从组件树中找到,因为我的自定义组件本身并不驻留在那里。

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

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-11-25 09:53:30

这是一个愚蠢的错误造成的。正如人们所设想的,添加的UIComponent确实会自动添加到ViewRoot中。然而,我从我的另一个自定义UIComponent中调用了一个自定义UIComponent (我在问题中提到的那个)(我没有提到这个,因为我忘记了它在那里):

UICodeEditor:

代码语言:javascript
复制
@Override
public void encodeAll(FacesContext context) throws IOException {
    UIEditPanel editor = new UIEditPanel();
    editor.encodeAll(context);
}

然后在模板中调用它,如下所示:

代码语言:javascript
复制
<!-- codeEditor is taghandler for UICodeEditor -->
<x:codeEditor />

在这里,UICodeEditor是自动添加到ViewRoot中的,但是它内部的UIEditPanel没有,因为我只是在调用encodeAll(context),所以UIEditPanel无法知道它的父级。一个快速的解决方法是手动设置子组件的父组件:

代码语言:javascript
复制
editor.setParent(this);

另一种方法(也许更好)是从UIComponentBase扩展(像我们通常所做的那样),而不是手动调用encodeAll(context),而只是将组件作为一个子组件添加到encodeBegin(...)中,而不是在encodeAll(...)中。

代码语言:javascript
复制
@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中,以便稍后可以重新呈现内容。

票数 1
EN

Stack Overflow用户

发布于 2010-11-24 15:47:29

我不确定getClientId(context)是否会返回myComponent。实际上,如果您的组件嵌套在NamingContainer组件(如<h:form> )中,他的ID将以该容器的ID作为前缀。

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

代码语言:javascript
复制
<h:form id="myForm">
    <x:myUiComponent id="myComponent" />

然后,您必须使用以下方法检索组件:

代码语言:javascript
复制
context.getViewRoot().findComponent("myForm:myComponent");

对于context.getViewRoot().findComponent("myComponent:testDiv"); (或context.getViewRoot().findComponent("myForm:myComponent:testDiv"); ),它将返回null,因为在服务器端的JSF树中没有这样的元素。守则:

代码语言:javascript
复制
writer.writeAttribute("id", getClientId(context) + ":testDiv", null);

将只在ID生成的组件上设置<div id="myForm:myComponent:testDiv">属性(即将页面中的<div id="myForm:myComponent:testDiv">发送给浏览器)。这个<div>组件在您的JSF树中不存在,因此无法在Java端检索。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4268546

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档