6

在我的基于 JSF 2 的应用程序中,我有一个包含(在其他 UI 组件中)一些复选框的表单。

在复选框上,我注册了 ajax 请求,它们在被选中时触发。ajax 请求实际上只会更新支持 bean 中另一个复选框的值。结果,另一个复选框也将被选中(当它重新渲染时 - 因为它将在渲染响应阶段从支持 bean 获取更新的值)。

在整个表单被提交并发生验证错误之前,这可以正常工作。然后,ajax 请求仍然有效并更改支持 bean 上的值,但在重新呈现更新后的复选框的阶段,它的值不是从支持 bean 中获取,而是来自从ComponentStateHelper类中获取的缓存值。

据我了解,这用于 JSF 2 的新功能,仅存储对组件树的部分更改。

我不明白的是:这与验证阶段有什么关系?StateHelper当验证发现错误时,为什么我的复选框的类中有缓存值?

4

1 回答 1

4

这是一个已知问题,并在此答案中进行了深入解释。简而言之,问题是因为要渲染<f:ajax render>但未被执行的无效组件<f:ajax execute>与原始提交的值一起保持无效状态。当 JSF 渲染输入组件时,JSF 会先检查提交的值是不是null然后显示,否则显示模型值。您基本上需要重置要呈现但未由 ajax 执行的输入组件的提交值。

为此,您可以使用ActionListener基本上执行以下操作的an

UIViewRoot viewRoot = context.getViewRoot();
PartialViewContext partialViewContext = facesContext.getPartialViewContext();
Set<EditableValueHolder> inputs = new HashSet<EditableValueHolder>();

// First find all to be rendered inputs and add them to the set.
findAndAddEditableValueHolders(partialViewContext.getRenderIds(), inputs);

// Then find all executed inputs and remove them from the set.
findAndRemoveEditableValueHolders(partialViewContext.getExecuteIds(), inputs);

// The set now contains inputs which are to be rendered, but which are not been executed. Reset them.
for (EditableValueHolder input : inputs) {
    input.resetValue();
}

这已被报告为JSF 问题 1060,并且已在OmniFaces库中实现了一个完整且可重用的解决方案(此处ResetInputAjaxActionListener为源代码,此处展示演示)。

于 2012-05-23T15:58:32.687 回答