webtier@glassfish.java.net

f:ajax, _at_ViewScope and conditionally rendered forms: JSF actions not firing

From: <webtier_at_javadesktop.org>
Date: Tue, 13 Jul 2010 03:46:14 PDT

Good day,

I am having trouble getting conditionally-rendered forms to execute actions in a backing JSF bean when using the f:ajax tag:

I have a simple JSF2 page consisting of 3 forms (containing a single h:commandButton each), of which the last 2 forms are conditionally rendered (using the "rendered" attribute) based on whether or not the previous form's commandButton's action has been executed (the action simply sets flags that enable the other form(s) to be rendered). The form submit buttons have f:ajax tags, and the backing bean is view-scoped (using the @ViewScope annotation); please see the code in this post.

The problem I am experiencing is that the JSF action assigned to the conditionally rendered form2's commandButton is not executed after the form has been rendered via a ajax call (triggered when pressing form1's commandButton). If I remove the f:ajax tags completely, everything works as expected (so the ViewScope is working as expected). Using a simple debug phase listener, I've also noticed that when pressing form2's commandButton, only the "RESTORE VIEW" and "RENDER RESPONSE" phases are executed. This prompted me to add a fourth form that simply refreshes the entire page using a standard non-ajax JSF postback; after doing that, the conditionally rendered form2's commandButton works, and fires the backing JSF action.

What am I missing? I've tried searching for this to no avail, and the closest match I could find was answers such as the "condition for the 'rendered' attribute returns false somewhere during the lifecycle" which does not seem to be the case. Please help.

----- JSF page: test.xhtml -----

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <h1>Ajax form test</h1>
        <h:form id="reRenderForm">
            <h2>Debug form used to re-render entire page without changing values</h2>
            <p>allowAction1: #{testBean.allowAction1}</p>
            <p>allowAction2: #{testBean.allowAction2}</p>
            <p>allowAction3: #{testBean.allowAction3}</p>
            <h:commandButton id="b0" value="Just rerender the page" action="#{testBean.reRender}"/>
        </h:form>
        <h:form id="form1">
            <h2>Form 1</h2>
            <p>This is form 1</p>
            <p>allowAction1: #{testBean.allowAction1}</p>
            <p>allowAction2: #{testBean.allowAction2}</p>
            <p>allowAction3: #{testBean.allowAction3}</p>
            <h:commandButton id="b1" value="Run action 1" action="#{testBean.action1}">
                <f:ajax render="@form :f2Panel"/>
            </h:commandButton>
        </h:form>

        <h:panelGroup id="f2Panel">
            <h:form id="form2" rendered="#{testBean.allowAction2}">
                <h2>Form 2</h2>
                <p>This is form 2</p>
                <p>allowAction1: #{testBean.allowAction1}</p>
                <p>allowAction2: #{testBean.allowAction2}</p>
                <p>allowAction3: #{testBean.allowAction3}</p>
                <h:commandButton id="b3" value="Run action 2" action="#{testBean.action2}">
                  <f:ajax render="@form :f3Panel"/>
                </h:commandButton>
            </h:form>
        </h:panelGroup>

        <h:panelGroup id="f3Panel">
            <h:form id="form3" rendered="#{testBean.allowAction3}">
                <h2>Form 3</h2>
                <p>This is form 3</p>
                <p>allowAction1: #{testBean.allowAction1}</p>
                <p>allowAction2: #{testBean.allowAction2}</p>
                <p>allowAction3: #{testBean.allowAction3}</p>
                <h:commandButton id="b4" value="Run action 3" action="#{testBean.action3}">
                </h:commandButton>
            </h:form>
        </h:panelGroup>
    </h:body>
</html>


----- JSF backing bean: TestBean.java -----

@ManagedBean(name = "testBean")
@ViewScoped
public class TestBean implements Serializable {

    private boolean allowAction1 = true;
    private boolean allowAction2 = false;
    private boolean allowAction3 = false;

    public boolean isAllowAction1() {
        return allowAction1;
    }

    public boolean isAllowAction2() {
        return allowAction2;
    }

    public boolean isAllowAction3() {
        return allowAction3;
    }

    public String action1() {
        System.out.println("1111------- ACTION 1 called, allowAction1: "+allowAction1+", allowAction2: "+allowAction2+", allowAction3: "+allowAction3);
        allowAction2 = true;
        return null;
    }

    public String action2() {
       System.out.println("2222------- ACTION 2 called, allowAction1: "+allowAction1+", allowAction2: "+allowAction2+", allowAction3: "+allowAction3);
       allowAction3 = true;
        return null;
    }

    public String action3() {
        System.out.println("3333------- ACTION 3 called, allowAction1: "+allowAction1+", allowAction2: "+allowAction2+", allowAction3: "+allowAction3);
        allowAction2 = false;
        allowAction3 = false;
        return null;
    }

    public String reRender() {
        System.out.println("=== RERENDER FORM called ===");
        return null;
    }
}
[Message sent by forum member 'faucamp']

http://forums.java.net/jive/thread.jspa?messageID=477494