UICodeEditor:@Overridepublic 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),而只是将组件作为getChildren.add(...)的子代添加到encodeBegin(...)而不是encodeAll(...):@Overridepublic 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中,以便稍后可以重新呈现内容.I am building a custom UIComponent and adding elements (and other stock UIComponents) inside it. The component renders ok, however it cannot be found from the ViewRoot.Let's say I have:ResponseWriter writer;@Overridepublic void encodeBegin(FacesContext context) throws IOException { writer = context.getResponseWriter(); writer.startElement("div", this); writer.writeText("testing", null); writer.writeAttribute("id", getClientId(context) + ":testDiv", null);}@Overridepublic void encodeEnd(FacesContext context) throws IOException { writer.endElement("div");}Adding that as:<x:myUiComponent id="myComponent" />This renders ok, however I cannot find the component or it's child div from the ViewRoot:context.getViewRoot().findComponent("myComponent"); // returns nullcontext.getViewRoot().findComponent("myComponent:testDiv"); // returns nullfindComponent("myComponent:testDiv"); // called within the custom component, throws java.lang.IllegalArgumentException?The same problem applies when I try to add other UIComponents as my custom component's children - they render succesfully, however cannot be found from the component tree as my custom component itself doesn't reside there.What's the trick here to get the components into the component tree?Edit: Adjusted the title to better reflect the question. 解决方案 This was caused by a stupid mistake. As one would suppose, the added UIComponent does get automatically added to ViewRoot. I was, however, calling a custom UIComponent (the one I was talking about in the question) from inside my other custom UIComponent (which I din't mention because I forgot that it was there) like this:UICodeEditor:@Overridepublic void encodeAll(FacesContext context) throws IOException { UIEditPanel editor = new UIEditPanel(); editor.encodeAll(context);}Then called this in a template like:<!-- codeEditor is taghandler for UICodeEditor --><x:codeEditor />Here, the UICodeEditor does get automatically added to the ViewRoot, however, UIEditPanel inside it does not, because I was simply calling encodeAll(context) and so the UIEditPanel has no way of knowing its' parent. A quick fix would be to manually set the parent of the child component:editor.setParent(this);Alternative approach (maybe better) would be to extend from UIComponentBase (as we normally do) and not manually call encodeAll(context) but just add the component as a child with getChildren.add(...) in encodeBegin(...) and not in encodeAll(...):@Overridepublic void encodeBegin(FacesContext context) throws IOException { UIEditPanel editor = new UIEditPanel(); getChildren().add(editor);}The getChildren().add() internally adds the current component as parent of the children.Considering the location of the child creation, it might be better to build them straight in the constructor and not override the encodeXXX methods at all, if there's no need to use ResponseWriter (if there is, then you need to override those). However, it is more flexible to override and manually call encoding, whatever you need.Also note that a custom UIComponent cannot directly be an <f:ajax render= target, because it isn't represented by a DOM element in the DOM tree. This this the same case as with composite components, where I tend to wrap the composite component implementation into a JSF managed panelGroup so that the contents can be re-rendered later on. 这篇关于JSF 2.0:如何添加UIComponents及其内容以查看根目录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 08-22 15:53