考虑以下事实可以理解问题的原因:
当在验证阶段针对特定输入组件的JSF验证成功时,则将提交的值设置为
null
,并将验证的值设置为输入组件的本地值。如果在验证阶段对特定输入组件的JSF验证失败,则提交的值将保留在输入组件中。
在验证阶段之后,如果至少一个输入组件无效,那么JSF将不会更新任何输入组件的模型值。JSF将直接进入渲染响应阶段。
当JSF渲染输入组件时,它将首先测试提交的值是否不是
null
,然后显示它;如果本地值不是null
,然后显示它,否则它将显示模型值。只要您与相同的JSF视图进行交互,就可以处理相同的组件状态。
因此,当针对特定表单提交的验证失败时,您碰巧需要通过不同的ajax动作甚至不同的ajax表单(例如,根据下拉选择或某些结果填充字段)来更新输入字段的值。模态对话框形式等),那么您基本上需要重置目标输入组件,以使JSF可以显示在调用动作期间编辑的模型值。否则,JSF仍将显示其本地值,如在验证失败期间一样,并将其保持在无效状态。
在 您的特定情况下
,方法之一是手动收集要由更新/重新呈现的输入组件的所有ID,
PartialViewContext#getRenderIds()然后由手动重置其状态和提交的值
EditablevalueHolder#resetValue()。
FacesContext facesContext = FacesContext.getCurrentInstance();PartialViewContext partialViewContext = facesContext.getPartialViewContext();Collection<String> renderIds = partialViewContext.getRenderIds();for (String renderId : renderIds) { UIComponent component = viewRoot.findComponent(renderId); EditablevalueHolder input = (EditablevalueHolder) component; input.resetValue();}您可以在
handleAddressChange()侦听器方法内部
ActionListener,也可以
<f:actionListener>在与调用
handleAddressChange()侦听器方法的输入组件相连的可重用实现中进行此操作。
回到具体问题,我想这是对JSF2规范的疏忽。当JSF规范强制执行以下命令时,对我们JSF开发人员而言将更加有意义:
- 当JSF需要通过ajax请求更新/重新呈现输入组件,并且该输入组件不包含在ajax请求的处理/执行中时,则JSF应该重置输入组件的值。
这已被报告为JSF问题1060和一个完整的,可重复使用的解决方案已在已实施OmniFaces库作为
ResetInputAjaxActionListener(源代码在这里,展示演示在这里)。
更新1:
从3.4版开始,PrimeFaces基于此思想还引入了一个完整且可重复使用的解决方案
<p:resetInput>。
更新2:
从版本4.0开始,
<p:ajax>有一个新的布尔属性
resetValues,该属性也可以解决此类问题,而无需其他标签。
更新3: 引入了JSF 2.2
<f:ajaxresetValues>,遵循与相同的想法
<p:ajax resetValues>。该解决方案现在是标准JSF API的一部分。



