5
votes

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!

2
Can you post a code for those two forms, and AJAX update attributes?partlov
I'm about to finish a small maven projectNicolas Labrot
Try to add explicitly render=":formB" inside f:ajax tag.partlov
It's works but I do not understand yet why it is different from the getRenderIds().add(formB.getClientId()); In fact the two forms are in 2 xhtml file fragment which do not see each other. Only the parent component see the 2 forms.Nicolas Labrot

2 Answers

4
votes

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:

2
votes

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.