5

I have custom control written in Java. For the sake of simplicity lets assume that it looks like this:

public class HelloworldControl extends UIComponentBase {
    @Override
    public void decode(FacesContext context) {
        String cid = this.getClientId(context);
        ...
        super.decode(context);
    }

    @Override
    public void encodeBegin(FacesContext context) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        writer.writeText("Hello world!", this);
        // I want a view!!
    }

    @Override
    public void encodeEnd(FacesContext context) throws IOException {
         ResponseWriter writer = context.getResponseWriter();
         ...
    }

    public void restoreState(FacesContext context, Object state) {
        Object values[] = (Object[]) state;
        ...
        super.restoreState(context, values[0]); 
    }

    public Object saveState(FacesContext context) {
        Object values[] = ...
    }
}

I would like to add programatically child control to it. For example I would like a child view control to render a view just under the Hellow world text.

How can i do this? What is the standard procedure to build dynamically a control?

To put it simply - I want programmatically build a hierarchy of standard components and I want to attach it to my control.

Cœur
  • 37,241
  • 25
  • 195
  • 267
W_K
  • 868
  • 4
  • 9
  • What do you mean with *"a view just under the Hello world text"*? – Sven Hasselbach Jun 08 '12 at 12:24
  • I tried to be strightforward as possible - I meant by this that this HelloWorldControl from example shows Hello world text (its in encodeBegin code) and I would like for it to load dynamically a view control and force it to render somewhere between encodeBegin and encodeEnd. – W_K Jun 08 '12 at 12:34

2 Answers2

4

The answer I think your looking for is implement the FacesComponent Interface There is detailed instructions that Keith Strickland put out on his blog:

http://xprentice.gbs.com/A55BAC/keithstric.nsf/default.xsp?documentId=82770C11FA7B9B21852579C100581766

It uses the initBeforeContents, buildContents, and initAfterContents methods to allow you to add children.

Hope that helps.

Toby Samples
  • 2,168
  • 14
  • 15
  • Thanks for the link Toby, but to add to this... If you're not sure what the class names are to do this take a look at this website which shows all of the IBM common and Extension Library controls, their class names and properties: http://www.openntf.org/xspext/xpages%20extension%20library%20documentation.nsf/xpages-doc/Controls.html – keithstric Jun 09 '12 at 15:53
1

You could do this by creating your UIComponent directly in your encodeBegin method:

public void encodeBegin(FacesContext context) throws IOException {
    ResponseWriter writer = context.getResponseWriter();

    writer.writeText("Hello world!", "");
    try{
        UIPassThroughText uiText= new UIPassThroughText();
        uiText.setText("Hello daddy!");
        uiText.encodeBegin(context);
        uiText.encodeChildren(context);
        uiText.encodeEnd(context);
    }

But I don't think that it is a good idea to do this, because then your child components are not added to the component tree...

EDIT: The answer of Toby Samples is the better one. I have undeleted this answer because it still works, but I am not proud of. To add the uiText to the component tree, you would have to use the this.getChildren().add(uiText) method.

Better to use an own renderer class as described f.e. here: XPages Extensibility API > Creating a Java Control in an NSF

Sven Hasselbach
  • 10,455
  • 1
  • 18
  • 26
  • How adding renderer can solve my problem ? I want to create hierarchy of standard components with standard renderers. – W_K Jun 08 '12 at 13:29
  • Adding a renderer will not solve your problem. But using the standard mechanisms (implementing the renderer class) will help that the resulting components will still be compatible for XPages. – Sven Hasselbach Jun 09 '12 at 13:52