views:

842

answers:

2

Hello! I have a tag class which extends UIComponent and UIOutput. In this class I have encodeBegin and encodeEnd which I can use my contextWriter to output any kinda html tag I want too by using writer.startElement("div", myComponent) and so on.

My problem now is that I need to insert for example a instead of using the writer.startElement. I can get this done by doing getChildren().add(HtmlCommandButton button = new HtmlCommandButton()); but when doing it like that I cant seem to output the component where I want them to appear, like I can with write.startElement.

Does anyone have any good solutions in how I can take advantage of richfaces tags, JSF tags and similar in my own taglibrary? In short what I would really want to do is inside my encodeBegin:

writer.startElement("a4j:commandButton", myComponent);
writer.writeAttribite("action", "#{Handler.myAction}", null);
writer.endElement("a4j:commandButton");

Thanks by advance

+1  A: 

Not really an answer, more of a guess, but maybe you could extend one of the facelets controls?

Alternatively, either use facelets directly - which seems to be exactly what you want really though I've not used it myself. Or you could add UIOutput controls where you want HTML to appear and set the value of each to the HTML you want to appear - this is exactly what f:verbatim does under the hood, or so it seems from looking at the source code :-)

Simon Gibbs
Yes Im already extending UIOutput. Im not sure what I would extend that gives me the ability to output other components instead of only outputting tags. Thanks for reply.
ChrisAD
I've looked around at some controls and edited the question. I've done nothing you couldn't do yourself with Google and the faces and facelets sources really though!
Simon Gibbs
Excellent. I will try this as soon as possible (probably within 48 hours as Im not at work these two days). Thank you very much for your time
ChrisAD
Facelets are essentially a replacement for using JSPs to define your pages.
McDowell
+1  A: 

You cannot use the ResponseWriter as you wish to. Two ways I can think of how to add child controls programmatically are either via the binding attribute (see this answer) or in the place where controls usually get created (in JSPs, that is in the tag class).

There are two ways for JSF components to contain other controls: as children or as named facets. Components always control how they render their facets; if they are to render their children, they must return true for getRendersChildren.

This is untested code, but the sequence goes something like this:

  @Override
  public boolean getRendersChildren() {
    return true;
  }

  @Override
  public void encodeBegin(FacesContext context)
      throws IOException {
    // should really delegate to a renderer, but this is only demo code
    ResponseWriter writer = context.getResponseWriter();
    writer.startElement("span", this);
    String styleClass = getStyleClass();
    writer
        .writeAttribute("class", styleClass, "styleClass");

    UIComponent headerComponent = getFacet("header");
    if (headerComponent != null) {
      headerComponent.encodeAll(context);
    }

    writer.startElement("hr", null);
  }

  @Override
  public void encodeChildren(FacesContext context)
      throws IOException {
    ResponseWriter writer = context.getResponseWriter();
    for (UIComponent kid : getChildren()) {
      kid.encodeAll(context);
      writer.startElement("br", null);
    }
  }

  @Override
  public void encodeEnd(FacesContext context)
      throws IOException {
    ResponseWriter writer = context.getResponseWriter();
    writer.endElement("span");
  }
McDowell
Excellent man. I just got to test this. The myComponent.encodeAll(context) was exactly what I was looking for. Thank you very much!
ChrisAD