Dynamic component creation
Hi,
I have got a problem with my custom component, which I could only solve with a hack. The component renders a tabbed page, the tabs are determined at runtime and thus have to be added dynamically. So basically, I put the information about the tabs into a backing bean and bind this to my component, which iterates over each tabItem and displays them accordingly.
So far so good, but here is the problem: My component must only add the headers once, so in beginEncode() , I do something like this:
if(!(getChildren().get(0)instanceof TabHeaderComponent))
{
TabHeaderComponent headerComponent =new TabHeaderComponent();
.....
}
I look at the child at position 0 and only if it is not a headerComponent, I create my header. This ensures, that I do not add headers repeatedly. Clearing the children is not an option, since this would remove all content from my page (the tabs would work though! :o)).
Thus, I wonder:
a) is encodeBegin() the right place to create my components?
b) if so, how can I avoid the ugly if/instance-of check?
c) where could I find documentation related to my problem?
Regards,
Tom
[1350 byte] By [
de_toma] at [2007-10-2 14:26:57]

I would suggest the following:
1. make your tab component implement NamingContainer
2. define an ID for the tab header component, e.g. "tabHeader".
3. in encodeBegin(), call findComponent("tabHeader") to determine whether or not the sub-component exists. If it does not exist, create it, set its ID to "tabHeader" and add it as a child.
public class UITab implements NamingContainer {
private static final String TAB_HEADER_ID = "tabHeader";
public void encodeBegin(FacesContext context) {
UITabHeader tabHeader = (UITabHeader) findComponent(TAB_HEADER_ID);
if (tabHeader == null) {
tabHeader = new UITabHeader();
tabHeader.setId(TAB_HEADER_ID);
getChildren().add(0, tabHeader);
}
...
}
}
Alternatively, if you want to separate your component and renderer in separate classes, write something like this instead:
public class UITab implements NamingContainer {
// ...
}
public class TabRenderer extends Renderer {
private static final String TAB_HEADER_ID = "tabHeader";
public void encodeBegin(FacesContext context, UIComponent component) {
UITabHeader tabHeader = (UITabHeader) component.findComponent(TAB_HEADER_ID);
if (tabHeader == null) {
tabHeader = new UITabHeader();
tabHeader.setId(TAB_HEADER_ID);
component.getChildren().add(0, tabHeader);
}
...
}
}
Geoff Rimmer
Hi Geoff,
thank you for your elaborate answer, but I still have some questions:
a) findComponent actually does the same thing as my code - I still feel that this is kind of awkward - checking whether some component exists or not. Isn't there a better place to put the component creation - a method like setProperties in the component's tag for example? I mean in the servlet API there is the init() method - is there no corresponidng method for JSF components?
b) In my opinion, the renderer should not add components - its only job is to render the component it is assigned to. Likewise, I think that the component's tag is not the right place to add this code either - yet what about having a init() method in the component which is called from within the tag's setProperties() method? Still not a really clean solution though!
Regards,
Tom