Question

I am trying to display HtmlInputText dynamically in a JSF page. However, I am getting

javax.faces.FacesException: Cannot add the same component twice: j_idt10:hitDyn

During the first request to the page the input text renders well. That exception happens during postback of the page, when I enter some text in the input component and press Enter. In the .xhtml page, I have the following code:

<h:form>
    <h:outputLabel value="Welcome!"></h:outputLabel>
    <f:metadata>
        <f:event type="preRenderView" listener="#{dynamicBacking.addDynComp}" />
    </f:metadata>
    <h:panelGroup id="dynOuter"></h:panelGroup>
</h:form>

In the backing bean, I have the following code:

@ManagedBean(name="dynamicBacking")
public class DynamicBacking {
    public void addDynComp() {
        Application app = FacesContext.getCurrentInstance().getApplication();
        HtmlInputText hit = (HtmlInputText)app.createComponent(HtmlInputText.COMPONENT_TYPE);
        hit.setId("hitDyn");
        UIComponent parent = findComponent("dynOuter");
        if( parent != null ) {
            parent.getChildren().add(hit);
        }
    }

    public UIComponent findComponent(final String id) {
        FacesContext context = FacesContext.getCurrentInstance(); 
        UIViewRoot root = context.getViewRoot();
        final UIComponent[] found = new UIComponent[1];
        root.visitTree(new FullVisitContext(context), new VisitCallback() {     
            @Override
            public VisitResult visit(VisitContext context, UIComponent component) {
                if(component.getId().equals(id)){
                    found[0] = component;
                    return VisitResult.COMPLETE;
                }
                return VisitResult.ACCEPT;              
            }
        });
        return found[0];
    }
}

I guess that there is some problem with restoring the state of the dynamic component in a postback. Am I adding the dynamic component too late in the lifecycle of the JSF page? I know that in ASP.NET I could add a dynamic control during Page.Load phase. But I can't so far figure out how to achieve the same in JSF. Please, help!

Était-ce utile?

La solution

The exception appears because the component is added in the tree on the initial page load. When performing a postback your listener gets called again and it tries to add another component with the same id and this causes the exception. A solution of the issue is to check if the request is NOT a postback when adding the component. The following code shows how to check for postback:

if (FacesContext.getCurrentInstance().isPostback()) {....
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top