How to rerender part of page with form in JSF 2.0?

mykola picture mykola · Apr 5, 2012 · Viewed 13.4k times · Source

Currently we're trying to move to JSF 2.0 from JSF 1.2 and one of the problem we've faced is that it's impossible to rerender part of the page that contains form. Like this (rerender outerDiv or forms themselves):

<h:panelGroup id="outerDiv">
    <h:form id="form1">...</h:form>
    <h:form id="form2">...</h:form>
</h:panelGroup>

I mean that if i update outerDiv everything is updated but the form (or forms) itself becomes broken and behaves strangely, at least ajax calls either don't work when first time triggered or instead of calling some bean's method they create new instance of that bean and do nothing (either with destroying previous with every call or just creating new one on first call and then do nothing). The problem can be solved by rerendering only components inside form, like this (update innerDiv1 and innerDiv2):

<h:panelGroup id="outerDiv">
   <h:form id="form1">
       <h:panelGroup id="innerDiv1">...</h:panelGroup>
   </h:form>
   <h:form id="form2">
       <h:panelGroup id="innerDiv2">...</h:panelGroup>
   </h:form>
</h:panelGroup>

but we have a lot of places where we include some page with ui:include and it's not very convenient to look inside that page and update certain components there. Besides we'll have to modify all these pages as many of them don't have common wrapper div inside forms and update each component separately will be very cumbersome and error prone.
So, is it possible to make JSF 2.0 correctly update part of page with 1-st approach like it was in JSF 1.2?


EDIT: it looks like the issue with form rendering is richfaces 4.2 issue as i use a4j:ajax (successor of a4j:support that was used with richfaces 3.3.3) and custom buttons based on rich:commandButton. When i substituted them with native jsf's f:ajax forms seems to be refreshed correctly. But issue with outer div is still actual

Answer

BalusC picture BalusC · Apr 5, 2012

This is related to partial state saving. If you ajax-update a component which in turn contains a form as one of its children, then its view state will get lost. Every 1st ajax request inside that form will fail because there's no view state. But if that ajax request is re-rendering the form itself, then it will work.

To fix this, you need to explicitly include the ID of the other form(s) in ajax render/update attribute next to outerDiv whenever it's invoked from another form.

E.g.

<h:form>
    <h:commandButton value="Update other forms">
        <f:ajax render="outerDiv form1 form2" />
    </h:commandButton>
</h:form>
<h:panelGroup id="outerDiv">
    <h:form id="form1">...</h:form>
    <h:form id="form2">...</h:form>
</h:panelGroup>

No, this will not result in an ajax response with duplicate components. It will just trigger JSF to prepare and save the state of those other forms.

See also: