values lost after validation error in JSF
I have two pages. Search page is the first page that takes user inputs. Second page shows the result set in datatable. Second page has 3 panel for resultset, update and create all in single page. Depending upon the which button being clicked, I am rendering panels true and false.
<h:panelGroup styleClass="panelGroup"
id="resultSet" rendered="#{bean.truefalse1}">
.
.
</h:panelGroup
<h:panelGroup styleClass="panelGroup"
id="updateForm" rendered="#{bean.truefalse2}">
.
.
</h:panelGroup
<h:panelGroup styleClass="panelGroup"
id="createForm" rendered="#{bean.truefalse3}">
.
.
</h:panelGroup>
From the search page I am setting these create and update panels to false and displaying only resultset.After the row from the result set is clicked I am showing updateForm panel but keeping create panel to false.
But here the problem is, If there is validation error, then the property that was set from search page is being lost and all the panels are shown.
How do I get the value(boolean true or false) that was set from search page previously, since I am not navigating to differen开发者_Go百科t page.
I have getters and setters for boolean property in second class. I even tried keeping hidden fields(i.e the boolean property that was set from search page). Shouldn't all the submitted values be recovered after validation error. Or just the ones we type in the form.
What is the best solution?
Any help is highly appreciated!!!
You indeed need to transfer the very same boolean properties to the next request. You can in theory use <h:inputHidden value="#{bean.boolean1}" />
for this, but unfortunately those will only be set during update model values phase, while you actually need it to be available during apply request values phase. Besides, they will also go lost when a validation error occurs.
There are three ways to fix this non-intuitive behaviour of h:inputHidden
(I've ever filed a bug against it at the Mojarra issue list, but they didn't seem to do anything with it).
First is to use the binding
on the h:inputHidden
instead:
<h:inputHidden binding="#{bean.hidden1}" />
This however requires changes in the way you get/set the boolean values in the backing bean code. For example:
private HtmlInputHidden hidden1 = new HtmlInputHidden(); // +getter +setter.
public void setBoolean1(boolean boolean1) {
hidden1.setValue(boolean1);
}
public boolean getBoolean1() {
return (Boolean) hidden1.getValue();
}
Second is to use Tomahawk's t:saveState
instead.
<t:saveState value="#{bean.boolean1}" />
The major advantage is that you don't need to change anything in the backing bean code. It will restore the value early before the apply request values phase. You only need to add extra libraries if not done yet, but as Tomahawk provides much more advantages than only the t:saveState
, such as the in basic JSF implementation missing components/features t:inputFileUpload
, t:dataList
, t:dataTable preserveDataModel="true"
, t:selectOneRadio layout="spread"
and so on, it is worth the effort.
The third way is to store them in a session scoped bean, but you actually don't want to do that for request scoped variables. It would only give "wtf?" experiences when the enduser has multiple tabs/windows open in the same session.
Edit: as per the comments, here's an SSCCE of the second way:
JSF page:
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<f:view>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<h:form id="form">
<h:inputHidden binding="#{myBean.hidden}" converter="javax.faces.Boolean" />
<h:commandButton value="submit" action="#{myBean.submit}"/>
<h:outputText value="Current boolean value: #{myBean.hidden.value}" />
</h:form>
</body>
</html>
</f:view>
MyBean class:
package mypackage;
import javax.faces.component.html.HtmlInputHidden;
public class MyBean {
private HtmlInputHidden hidden = new HtmlInputHidden();
public void submit() {
if (hidden.getValue() == null) {
hidden.setValue(true); // Set to true on 1st submit.
} else {
hidden.setValue(!((Boolean) hidden.getValue())); // Toggle true/false.
}
}
public HtmlInputHidden getHidden() {
return hidden;
}
public void setHidden(HtmlInputHidden hidden) {
this.hidden = hidden;
}
}
The relevant part of faces-config.xml
:
<managed-bean>
<managed-bean-name>myBean</managed-bean-name>
<managed-bean-class>mypackage.MyBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
Playground environment is JSF 1.2_13 on Tomcat 6.0.20.
精彩评论