Question

Setup: I have 2 forms A & B I have a commandLink in form A:

<h:commandLink actionListener="#{homeView.selectDiv('homeUpdates')}">#{msg.homeUpdates}
   <f:ajax render=":B" execute="@this" />
</h:commandLink>

...which updates form B.

The problem is that when I click the ajax link, it rebuilds form A as well and gets an exception from a ui:repeat I have. Is this correct behaviour? Should it rebuild form A as well?

I am using JSF 2.2 and form A contains a ui:fragment=>ui:include=>ui:repeat

=====Added SSCCE======= The following code does not run after pressing Update B! twice. It gives an exception of duplicate id. The value for ui:repeat is irrelevant

<h:head>
</h:head>

<h:body>
    <h:form id="A">
        <ul class="tableView notification">
            <ui:repeat var="notification" value="#{dashboardBean.notifications}">
                <li>
                    xx
                </li>
            </ui:repeat>
        </ul>

        <h:commandLink value="Update B!" listener="#{dashboardBean.toggleRendered}">
            <f:ajax execute="@this" render=":B" />
        </h:commandLink>

    </h:form>

    <h:form id="B">
    </h:form>
</h:body>
Was it helpful?

Solution

Upon initial request the view is created, upon postbacks the view is restored. To recite some points of JSF 2.2 specification for clarity (emphasis mine):

P. 2.2.1:

If the request is not a postback ... call createView() on the ViewHandler. If the request is a postback, ... call ViewHandler.restoreView(), passing the FacesContext instance for the current request and the view identifier, and returning a UIViewRoot for the restored view.

P. 2.5.8:

Selected components in a JSF view can be priocessed (known as partial processing) and selected components can be rendered to the client (known as partial rendering).

P. 13.4:

The JavaServer Faces lifecycle, can be viewed as consisting of an execute phase and a render phase. Partial traversal is the technique that can be used to “visit” one or more components in the view, potentially to have them pass through the “execute” and/or “render” phases of the request processing lifecycle.

When you use AJAX, PartialViewContext class will contain all the information that's needed to traverse the restored view.


So, to get back to your question, under <f:ajax render=":B" execute="@this" /> setup, only the form with id="B" will be rerendered, which implies <h:form id="B">, no form nestings, etc.

Regarding your 'doesn't work' comment the simple test case with a plain view scoped managed bean gave me the expected results:

<h:form id="A" >
    <h:outputText value="#{twoFormsBean.a}"/>
    <h:commandLink actionListener="#{twoFormsBean.actionA}">
        Update B!
        <f:ajax execute="@this" render=":B"/>
    </h:commandLink>
</h:form>
<h:form id="B" >
    <h:outputText value="#{twoFormsBean.b}"/>
    <h:commandLink>
        Update Both!
        <f:ajax execute="@this" render=":A :B"/>
    </h:commandLink>
</h:form>

with

@ManagedBean
@ViewScoped
public class TwoFormsBean implements Serializable {

    private String a = "A";//getter
    private String b = "B";//getter

    public void actionA(ActionEvent ae) {
        a = "newA";
        b = "newB";
    }

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top