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]
# 1

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

grimmera at 2007-7-13 12:47:11 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 2

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

de_toma at 2007-7-13 12:47:11 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...