Search code examples
ajaxformsjsfjsf-2viewstate

JSF2: Form ajax action makes another form's view state to be lost


I have a simple page consisting of two forms. They cannot be displayed simultaneously (one toggles the other). Here is the code:

<h:body>

    <ui:composition template="/elements/templateWithMenu.xhtml">            
        <ui:define name="content">

            <p:dialog id="question1DialogId" widgetVar="question1Dialog" resizable="false" closable="false" visible="true">                             

                <h:panelGroup id="questionStep1Group">
                    <h:form id="questionStep1Form" rendered="#{newPoll2.displayQuestionStep1}">

                        <h:commandLink value="next" action="#{newPoll2.questionStep1Completed()}" class="btn" >
                            <f:ajax execute="@form" render=":questionStep2Form :questionStep1Group :questionStep2Group"/>
                        </h:commandLink>

                    </h:form>
                </h:panelGroup>

                <h:panelGroup id="questionStep2Group">
                    <h:form id="questionStep2Form"  rendered="#{newPoll2.displayQuestionStep2}">

                        <h:commandLink value="cancel" action="#{newPoll2.questionStep2Cancelled()}" class="btn" >
                            <f:ajax execute="@form" render=":questionStep1Form :questionStep1Group :questionStep2Group" />
                        </h:commandLink>

                    </h:form>
                </h:panelGroup>

            </p:dialog>

        </ui:define>
    </ui:composition>

</h:body>

questionStep1Completed() and questionStep2Cancelled() simply toggle the booleans used in rendered attribute.

The problem is with the view states. When the page is first loaded, clicking on "next" will work, and it will be replaced with the "cancel" link. But when I click on the "cancel" link, it needs to be clicked twice in order for it to be replaced with with the "next" link. I can see that the first click makes the request with no view state, and the second (successful) one makes a request with it.

I saw this question, and this link, and as you can see, I've added form ids in the render attribute, but it still doesn't work. Any ideas?

Thanks


Solution

  • You're conditionally rendering the forms themselves and hence the other form isn't physically available in the HTML DOM tree at the moment the ajax request is been prepared. If you wrap the form's content in another <h:panelGroup> and move the rendered attribute to there, then it ought to work.