4

I know about startElement, endElement, and writeAttribute methods on ResponseWriter. My problem is that I want to for example output a h:commandLink by declaring it like HtmlCommandLink link = new HtmlCommandLink(); .

How can I output other UIComponents like this in my own component? I might want to use some RichFaces ajax stuff in my components aswell so hoping I can avoid making it all by scratch.

Edit: What I'm trying to do is create my own tag library with the following tag <myTags:commentTree>. Every comment have a reply button, when the reply button is clicked I render the reply form beneath the comment. Once that is rendered, I would like to output for example the richfaces <a4j:commandButton> component. This have to be done inside my own java tag file which Ive called for CommentsTreeUI.java.

Normally I output all my elements that display the forms and buttons with writer.startElement("input", myComponent); writer.writeAttribute("type", "button", null); but if I could instead do for example startElement("a4j:commandbutton", myComponent) that would help my ALOT since it has all the built in ajax features etc.

Any clues?

Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
Chris Dale
  • 2,222
  • 2
  • 26
  • 39

3 Answers3

3

This problem was solved by adding new components by using

HtmlCommandButton button = new HtmlCommandButton();
button.encodeAll(context);
Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
Chris Dale
  • 2,222
  • 2
  • 26
  • 39
  • I know the question is very old but I was doing the same thing like this. The problem with this approach is that HtmlCommandButton doesn't get parent assigned, even though it is rendered ok. You need to call `button.setParent(this)` specifically. Check: http://stackoverflow.com/questions/4268546/jsf-2-0-how-to-add-uicomponents-and-their-contents-to-view-root Just a FYI for anybody reading this question. – Tuukka Mustonen Nov 26 '10 at 09:27
  • It is even better to not create components via 'new' but like here: http://stackoverflow.com/questions/19998802/how-to-add-component-programmatically-dynamically-to-a-pdatatable-facet – Kukeltje Nov 26 '15 at 11:38
2

You can do something like this:

HtmlCommandLink link = new HtmlCommandLink();
getChildren().add(link);

It does depend on what you want to do with the child components though i.e. if you want them surrounded with custom HTML (in an HTML list, for example) you will need something a bit more complex.

  • Very very interesting. Atm by doing the getChildre().add(link) it appends my button/link all the way on the end of the page. How can I output it where I want it in my sequence of htmloutputs? For example Im writing a div and I want the link to be within that div. Thanks alot so far! – Chris Dale Mar 16 '09 at 15:21
  • To sum it up I basicly want to add those child components where I want them. Atm they just append at the end of the GUI. – Chris Dale Mar 16 '09 at 15:39
  • Have you tried calling encodeBegin(...) etc on those components you want to render? –  Mar 16 '09 at 16:27
  • hmm no I havent. I have encodeBegin and encodeEnd in my program, but everything I render is done in my encodeBegin method. Its really big with several hundred lines of code atm. Am I doing this the wrong way maybe? – Chris Dale Mar 16 '09 at 17:47
0

One approach to making composite controls is to use the binding attribute to associate the tag with your own code:

<f:view>
    <h:form>
        <h:panelGroup binding="#{compositeControlBean.panelGrid}" />
    </h:form>
</f:view>

The bean configuration in faces-config.xml:

<managed-bean>
    <managed-bean-name>compositeControlBean</managed-bean-name>
    <managed-bean-class>
        composite.CompositeControlBean
    </managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
</managed-bean>

The bean code:

/**
 * Configure this bean in request scope as "compositeControlBean".
 */
public class CompositeControlBean {

  private transient UIComponent panelGrid;

  public UIComponent getPanelGrid() {
    if (panelGrid == null) {
      panelGrid = createCompositePanel();
    }
    return panelGrid;
  }

  public void setPanelGrid(UIComponent panelGrid) {
    this.panelGrid = panelGrid;
  }

  private UIComponent createCompositePanel() {
    initContextMemebers();

    UIComponent commandLink = createCommandLink();

    String id = view.createUniqueId();
    UIComponent panelGrid = application
        .createComponent("javax.faces.HtmlPanelGroup");
    panelGrid.setId(id);
    panelGrid.setRendererType("javax.faces.Group");

    panelGrid.getChildren().add(commandLink);

    return panelGrid;
  }

  private UIComponent createCommandLink() {
    // create control
    String id = view.createUniqueId();
    UIComponent commandLink = application
        .createComponent("javax.faces.HtmlCommandLink");
    commandLink.setId(id);
    commandLink.setRendererType("javax.faces.Link");
    // set attributes (bind to printHello method)
    Map<String, Object> attributes = commandLink
        .getAttributes();
    MethodExpression action = expressionFactory
        .createMethodExpression(elContext,
            "#{compositeControlBean.printHello}",
            String.class, new Class<?>[0]);
    attributes.put("value", "print hello");
    attributes.put("actionExpression", action);
    return commandLink;
  }

  private transient FacesContext context;
  private transient Application application;
  private transient ELContext elContext;
  private transient ExpressionFactory expressionFactory;
  private transient UIViewRoot view;

  private void initContextMemebers() {
    context = FacesContext.getCurrentInstance();
    application = context.getApplication();
    elContext = context.getELContext();
    expressionFactory = application.getExpressionFactory();
    view = context.getViewRoot();
  }

  public String printHello() {
    System.out.println("Hello");
    return null;
  }

}
McDowell
  • 107,573
  • 31
  • 204
  • 267