Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSF ViewState not updated when submitting 2 forms

I have a though issue with JSF 2. I use Mojarra 2.1.14 with Primefaces 3.1.4

I have a page with 2 forms : formA and formB. The two forms contains each the ViewState in an hidden input field.

<h:form id="formA" binding="#{sessionBean.formA}">
    <h:commandButton value="formA" action="#{sessionBean.actionA}">
        <f:ajax/>
    </h:commandButton>
</h:form>

<h:form id="formB" binding="#{sessionBean.formB}">
    <h:commandButton value="formB" action="#{sessionBean.actionB}">
        <f:ajax/>
    </h:commandButton>
</h:form>

User submits formA with an Ajax action. Inside the Java action I update explicitly formA and formB (which are binded).

public void actionA(){
    FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add(formA.getClientId());
    FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add(formB.getClientId());
    System.out.println("action A!!");
}

public void actionB(){
    System.out.println("action B!!");
}

In the Ajax responses there is the HTML code for formA and formB ( element) and the ViewState.

JSF updates the HTML of formA and formB and set the ViewState of the calling form : formA. formB do not contains any ViewState.

User submit formB with an Ajax action. Because ViewState is not defined, postBack is false and the renderResponse is set to true in the RESTORE phase, skipping the INVOKE APPLICATION phase: the action is not called. After the response VIEW_STATE is updated and if user sumbit formB, the action is called.

Is it a JSF 2 bug or limitation? Or Do I do something wrong ?

You can find a maven projet on GitHub: https://github.com/nithril/jsf-multiple-form

Thanks in advance for your help!

like image 920
Nicolas Labrot Avatar asked Feb 01 '13 22:02

Nicolas Labrot


2 Answers

Problem you are facing is connected with known issue with JSF JavaScript library. Workaround is to explicitly set client id of another form in rendered attribute of f:ajax tag:

<h:form id="formA" binding="#{sessionBean.formA}">
  <h:commandButton value="formA" action="#{sessionBean.actionA}">
    <f:ajax render=":formB @form"/>
  </h:commandButton>
</h:form>

<h:form id="formB" binding="#{sessionBean.formB}">
  <h:commandButton value="formB" action="#{sessionBean.actionB}">
    <f:ajax render=":formA @form"/>
  </h:commandButton>
</h:form>

More about this:

  • Ajax rendering of content which contains another form
  • javax.faces.ViewState is missing after ajax render
  • Rendering other form by ajax causes its view state to be lost, how do I add this back?
like image 120
partlov Avatar answered Nov 19 '22 20:11

partlov


There is an alternative trick if you use MyFaces 2.0.x / 2.1.x that will update the forms correctly, adding the following script:

window.myfaces = window.myfaces || {};
myfaces.config = myfaces.config || {};
//set the config part
myfaces.config.no_portlet_env = true; 

See JSF Ajax and Multiple Forms.

This option is a lot better because you don't need to worry about fix every place in your webapp where you use multiple forms, just add it to the main template and that's it.

like image 2
lu4242 Avatar answered Nov 19 '22 20:11

lu4242