Thank you very much Volker, your answer is very interesting.
My problem is very similar to the one you solved with your example. Going under, I also need to generate components within my own jsf component, and not only from a binding variable. So, as an example, think about a structure in memory that should be rendered in a page, and that the rendered component should, with a determined behavior, interact with the user: for example the component could render links or command buttons that have an action bounded to them.
Actually I'm doing exactly what you've done in your example, but during rendering phase of my component. All is working OK if I use myfaces, but if I switch to Sun RI that, for default, caches 15 views, I get a duplicate component id every time a page is reloaded for some reason. I can workaround the problem disabling the caching of views, but my question is more philosophical than practical: is it right to create components during the rendering phase of my component or the component should not depends from other widgets and should only render its own portion of html (including, for example, all form related components)?
My question so is more a check on what I'm doing with my component...Am I wrong with this approach? Is my (and of course your) solution "JSF oriented" (note...is quoted :) or is it only a tricky way to resolve this kind of problem?
Maybe it's a silly problem...

Regards,
Pierpaolo

Volker Weber wrote:
Hi Pierpaolo,

i'm not sure what exactly you problem is, because you don't write how
you are adding your generated componets to the view tree. but maybe this
helps you:

The easyest way to render dynamic appication created components is
(imho) to have a panel with binding attribute in yout jsf page, and
create the UIPannel including all children in your Application. You need
to assign a unique id to each application generated component to avoid
dublicated id exceptions.

Simple exampe:

----- jsf ----------------------------
 <h:panelGroup binding="#{testBean.panel}"/>
----- /jsf ---------------------------

----- java ---------------------------
  private String name;
  private int age;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }

  public UIPanel getPanel() {
    if (panel == null) {
      createPanel();
    }
    return panel;
  }

  public void setPanel(UIPanel panel) {
    this.panel = panel;
  }

  private void createPanel() {
    Application application =
FacesContext.getCurrentInstance().getApplication();
    // componentType and rendererType taken from HtmlPanelGroupTag
    panel = (UIPanel)
application.createComponent(HtmlPanelGroup.COMPONENT_TYPE);
    panel.setRendererType("javax.faces.Group");
    panel.setId("gen_panel");

    // componentType and rendererType taken from HtmlOutputLabelTag
    HtmlOutputLabel label = (HtmlOutputLabel)
        application.createComponent(HtmlOutputLabel.COMPONENT_TYPE);
    label.setRendererType("javax.faces.Label");
    label.setId("labelName");
    label.setFor("form:name");
    label.setValue("Name :");
    panel.getChildren().add(label);

    // componentType and rendererType taken from HtmlInputTextTag
    HtmlInputText text = (HtmlInputText)
        application.createComponent(HtmlInputText.COMPONENT_TYPE);
    text.setRendererType("javax.faces.Text");
    text.setId("name");
    ValueBinding vb = application.createValueBinding("#{testBean.name}");
    text.setValueBinding("value", vb);
    panel.getChildren().add(text);

    // componentType, rendererType and escape taken from VerbatimTag
    UIOutput verbatim =
        (UIOutput) application.createComponent("javax.faces.Output");
    verbatim.setRendererType("javax.faces.Text");
    verbatim.getAttributes().put("escape", Boolean.FALSE);
    verbatim.setId("verbatimName");
    verbatim.setValue("<BR>");
    panel.getChildren().add(verbatim);

    label = (HtmlOutputLabel)
        application.createComponent(HtmlOutputLabel.COMPONENT_TYPE);
    label.setRendererType("javax.faces.Label");
    label.setId("labelAge");
    label.setFor("form:age");
    label.setValue("Age :");
    panel.getChildren().add(label);

    text = (HtmlInputText)
        application.createComponent(HtmlInputText.COMPONENT_TYPE);
    text.setRendererType("javax.faces.Text");
    text.setId("age");
    vb = application.createValueBinding("#{testBean.age}");
    text.setValueBinding("value", vb);
    panel.getChildren().add(text);

    verbatim =
        (UIOutput) application.createComponent("javax.faces.Output");
    verbatim.setRendererType("javax.faces.Text");
    verbatim.setId("verbatimAge");
    verbatim.getAttributes().put("escape", Boolean.FALSE);
    verbatim.setValue("<BR>");
    panel.getChildren().add(verbatim);
  }
----- /java ---------------------------


will create the same view as the following

----- jsf ----------------------------
<h:panelGroup >

  <h:outputLabel for="" value="Name :" />
  <h:inputText id="name" value="#{testBean.name}"/>
  <f:verbatim><br></f:verbatim>

  <h:outputLabel for="" value="Age :" />
  <h:inputText id="age" value="#{testBean.age}"/>
  <f:verbatim><br></f:verbatim>

</h:panelGroup>
----- /jsf ---------------------------


Regards,
  Volker


Pierpaolo Follia wrote:
  
Hi guys.
This is not a MyFaces related problem, but a JSF related problem. Maybe
someone here could help me.
I'm writing a set of components for a new web application based on JSF.
Among requisites there is the need to build some forms in a dynamic way:
the application will sell products that will change in the future, and
the request from our committee is that (only for some product) forms are
to be auto-generated from a xml structure (or something similar) that
can be built using product info stored into the database.
Now my problem is this: I have created a jsf components that reads the
xml and creates new inputs components using validations and conversions
directly from the passed informations (using Shale and its validator
tags I can add _javascript_ validation too!). It's great, but I don't
think it's the right approach to the problem, because I'm creating new
components dynamically during the rendering phase of my component and I
have to make them not transient to allow the lifecycle to be applied to
my fresh created components. So, when the page is reloaded for some
reason, I get a duplicate id error, 'cause I'm adding components in the
view that I've already added before. I can check in some way if I have
to add or not my new inputs, but for reasons I can't explain, it is not
always possible for me to do this check.
Where I'm wrong with this problem? Is my solution totally wrong or is
there a way to safely add not transient components to my view without
the duplicate id problem?

Thanks.

Regards,
Pierpaolo

    

  

-- 
Pierpaolo Follia
Wave S.r.l. - Vai Benaco 24/B, Bedizzole (BS)
Telefono: +39 030 687561
Fax: +39 030 6875690

Reply via email to