1

I have following sample code. Initially, only commandButton Two is visible. When I click this button, commandButton One is also visible. But when I click One, the backing-bean method click1 does not get fired.

Following is my code:

xhtml

<h:form id="form1">
    <h:inputHidden id="show" value="#{bean.show1}" />
    <h:commandButton id="button1" value="One" action="#{bean.click1}"
        rendered="#{bean.show1}" />
</h:form>
<h:form id="form2">
    <h:inputHidden id="show" value="#{bean.show1}" />
    <h:commandButton id="button2" value="Two" action="#{bean.click2}" />
</h:form>

backing-bean

@RequestScoped
@Named("bean")
public class JsfTrial implements Serializable {

    private static final long serialVersionUID = 2784462583813130092L;

    private boolean show1; // + getter, setter

    public String click1() {
        System.out.println("Click1()");
        return null;
    }

    public String click2() {
        System.out.println("Click2()");
        setShow1(true);
        return null;
    }

}

I found a very informative answer by BalusC.

If I understand it correctly, my problem is due to point 5 of this answer.

Does that also mean we can not use hidden commandButton with @RequestScoped backing-bean?

Community
  • 1
  • 1
Atul Acharya
  • 497
  • 2
  • 8
  • 21

1 Answers1

6

You can use the request scope, you should only pass the condition as a request parameter to the subsequent requests by <f:param> instead of by a JSF hidden input field <h:inputHidden>. The value of the hidden input field is only set in the model during Update Model Values phase, while the condition of the rendered attribute is already evaluated during Apply Request Values phase which is earlier.

So, use <f:param> instead of <h:inputHidden>:

<h:form id="form1">
    <h:commandButton id="button1" value="One" action="#{bean.click1}"
        rendered="#{bean.show1}">
        <f:param name="show1" value="#{bean.show1}" />
    </h:commandButton>
</h:form>
<h:form id="form2">
    <h:commandButton id="button2" value="Two" action="#{bean.click2}">
        <f:param name="show1" value="#{bean.show1}" />
    </h:commandButton>
</h:form>

This way you can extract them as request parameter in bean's (post)constructor.

public JsfTrial() {
    String show1 = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("show1");
    this.show1 = (show1 != null) && Boolean.valueOf(show1);
}

Ugly, but CDI doesn't offer a builtin annotation which substituties JSF's @ManagedProperty("#{param.show1}"). You could however homegrow such an annotation.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555