我正在开发一个表格为
的JSF应用程序<h:inputText value="#{model.firstname}" />
<h:inputText value="#{model.employeeNumber}" converter="javax.faces.Integer"/>
...
这是使用bean验证的模型:
@NotNull(message="Please enter a surname")
private String firstname;
@Min(value=1)
@Max(value=2000)
private Integer employeeNumber;
...
//setters and getters
除了明确编码的&#39; back&#39;之外,一切都很好用。页面中的按钮转到上一页/表单。
我希望用户输入的值在返回上一页时再次恢复,无论数据是否有效。例如,如果用户将abc
输入employeeNumber
字段,则此字符串无法存储到模型上的Integer
。
我知道JSF将用户输入的值存储到&#34;请求值&#34;对于每个UIComponent
。正是这些我想要恢复而不是我的模型,因为上面的表格还没有验证它的数据。
我该怎么做?
(当用户点击提交时,将进行数据验证。)
答案 0 :(得分:2)
我过去只处理过这个问题 - 不使用@NotNull
,@Min
和@Max
等验证注释。使用这些注释时,无效数据无法应用于模型,因此无法将状态保存在服务器上。
相反,我必须在Submit按钮后面的方法中编写验证逻辑。缺点是JSF没有为你工作;你必须自己做。好处是你可以更准确地控制验证的确切时间和方式。
答案 1 :(得分:2)
我的同事刚才提到可能有办法用omnifaces来实现这个目标
截至目前,有。 OmniFaces已经有很多东西可用,除了只有一个小的缺失关键部分。我只是committed一个Hacks#getStateHelper()
到2.3 SNAPSHOT,它应该将受保护的UIComponent#getStateHelper()
方法公开。然后,自1.0以及EditableValueHolderStateHelper
以来已经在OmniFaces中使用<o:form>
and <o:ignoreValidationFailed>
的帮助,无论转换/验证错误如何(如“后退”按钮应该这样),都可以调用动作。
因此,如果您确定至少使用OmniFaces 2.3(目前仅作为SNAPSHOT使用),那么您可以使用以下会话范围的帮助bean来实现此要求,并使用多个OmniFaces实用程序类Faces
,{{1 }和Hacks
:
EditableValueHolderStateHelper
需要在表单组件的@Named
@SessionScoped
public class Forms implements Serializable {
private transient Map<String, StateHelper> states = new ConcurrentHashMap<>();
public void saveState(ComponentSystemEvent event) {
UIComponent form = event.getComponent();
FacesContext context = Faces.getContext();
StateHelper state = Hacks.getStateHelper(form);
EditableValueHolderStateHelper.save(context, state, form.getFacetsAndChildren());
states.put(Faces.getViewId(), state);
}
public void restoreState(ComponentSystemEvent event) {
StateHelper state = states.get(Faces.getViewId());
if (state != null) {
UIComponent form = event.getComponent();
FacesContext context = Faces.getContext();
EditableValueHolderStateHelper.restore(context, state, form.getFacetsAndChildren());
}
}
public void removeState() {
states.remove(Faces.getViewId());
}
}
事件期间调用saveState
。需要在表单组件的postValidate
事件期间调用restoreState()
。在成功操作期间需要调用postAddToView
。以下是一个示例表单:
removeState()
这种方法的主要优点是不需要修改现有的验证规则和支持bean,因此保留了JSF和BV的所有优点。
每当您在关联表单的组件树结构中进行更改时,请确保清除服务器会话状态和/或增加<o:form>
<f:event type="postAddToView" listener="#{forms.restoreState}" />
<f:event type="postValidate" listener="#{forms.saveState}" />
<h:inputText value="#{bean.string}" required="true" />
<h:inputText value="#{bean.integer}" required="true" />
<h:commandButton value="save" actionListener="#{forms.removeState()}" action="#{bean.save}" />
<h:commandButton value="back" action="#{bean.back}">
<o:ignoreValidationFailed />
</h:commandButton>
<h:messages />
</o:form>
类serialVersionUID
,否则您必须进行预先检查和/或妥善处理异常。为表单和输入组件提供固定ID也是strongly recommended。