I have the following basic (and maybe stupid) understanding problem in JSF:
There is one JSF page "testPage.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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:view>
<h:body>
<h:form>
<h:commandLink id="B1" value="B1" action="#{testBean.ctrl}"/>
<h:commandLink id="B2" value="B2" action="#{testBean.ctrl}"
rendered="#{testBean.renderB2}"/>
</h:form>
</h:body>
</f:view>
</html>
And one backing bean "TestBean.java" :
package test;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
@ManagedBean(name="testBean")
@RequestScoped
public class TestBean implements Serializable {
public static final long serialVersionUID = 1L;
private boolean renderB2 = false;
public String ctrl() {
setRenderB2(true);
System.out.println("ctrl() is called.");
return null;
}
public boolean getRenderB2() {
return renderB2;
}
public void setRenderB2(boolean renderB2) {
this.renderB2 = renderB2;
}
}
So both links have TestBean.ctrl()
as action.
First only B1
is rendered. Clicking B1
causes execution of TestBean.ctrl()
and B2
is rendered too.
However, clicking B2
then does not execute TestBean.ctrl()
.
And this is my question: Why is the action method not executed when clicking B2
?
Probably it is because B2
is not rendered again.But why does that prevent the execution of the action method (called by the previously rendered B2
link)?
That's because the rendered
attribute is re-evaluated again during apply request values phase of the form submit. If an UIInput
or UICommand
component is not rendered at that point, then JSF won't apply the request values for the component. I.e. the UIInput
component's model value will not be updated and the UICommand
component's action will not be invoked.
Because your bean is request scoped, it's been trashed by end of the response which displays the form and a brand new one is been created by start of the request of the form submit.
You have to preserve any request scoped properties responsible for the rendered
attribute. The easiest way is to place the bean in the view scope by marking it @ViewScoped
and ensuring that you return null
or void
from action methods which should postback to the same view.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With