经过验证错误后续Ajax请求获取值从UI组件,而不是从豆类是从、而不、豆类、组件

2023-09-11 22:30:21 作者:我的一生、只为你等待

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

In my JSF 2 based application I have a form that includes (amongst other UI components) some checkboxes.

在我已经注册了消防检查时,Ajax请求的复选框。 Ajax请求实际上只是更新了支持bean的另一个复选框的值。 其结果是,其他的复选框也将被检查(当它被重新呈现 - 因为它会从后台bean中呈现响应阶段更新后的值)。

On the checkboxes I have registered ajax requests that fire when they are checked. The ajax requests will actually just update the value of another checkbox in the backing bean. As a result the other checkbox will also be checked (when it gets re-rendered - as it will take the updated value from the backing bean in the render response phase).

这正常工作,直到整个表单被提交并出现验证错误。 然后Ajax请求仍然工作,改变支持bean,但在该阶段重新呈现更新的复选框,它的价值是不是从后台bean但从取自 ComponentStateHelper 类。

This works fine until the whole form gets submitted and validation errors occur. Then the ajax requests still work and change the value on the backing bean but in the phase of re-rendering the updated checkbox the value for it is not taken from the backing bean but from a cached value that is taken from a ComponentStateHelper class.

据我了解,这是用于JSF 2的新功能只存储组件树部分改变。

As far as I understand this is used for the new feature of JSF 2 to only store partial changes to the component tree.

我不明白的是:这是如何与验证阶段?为什么会出现在 StateHelper 类为我的复选框,当验证发现错误缓存值?

What I do not understand is: How is this related to the validation phase? Why is there a cached value in the StateHelperclass for my checkbox when the validation found errors?

推荐答案

这是一个已知的问题,在深入的解释this回答。简而言之,该问题是由于失效的组件,这些组件通过&LT呈现; F:AJAX渲染> 但不被执行< F:AJAX执行> 仍处于无效状态以及原始提交的值。当JSF呈现输入组件,JSF首先会检查提交的值不是,然后显示它,否则它会显示模型的价值。基本上,您需要重新输入组件,这些组件要呈现的提交的值,但不会被阿贾克斯执行。

This is a known problem and explained in depth in this answer. In a nutshell, the problem is caused because the invalidated components which are to be rendered by <f:ajax render> but are not been executed by <f:ajax execute> remains in an invalidated state along with the original submitted value. When JSF renders the input component, JSF will first check if the submitted value is not null and then display it, else it will display the model value. You basically need to reset the submitted value of input components which are to be rendered, but which are not been executed by ajax.

要实现这一点,您可以使用 的ActionListener 其中的基本的执行以下操作:

To achieve this, you can use an ActionListener which basically does the following:

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 (来源$ C ​​$ C 这里和展示演示这里)。

This has been reported as JSF issue 1060 and a complete and reuseable solution has been implemented in the OmniFaces library as ResetInputAjaxActionListener (source code here and showcase demo here).