点击h:commandLink后部分a4j:commandLink触发页面无限加载问题
问题分析与解决方案:a4j:commandLink在表单验证失败后无限加载的差异问题
首先我们来拆解这个问题的核心差异和背后的原因:
为什么两个按钮表现不同?
当你点击Save按钮(h:commandLink)时,它会触发整个表单的验证流程。如果表单字段无效(比如必填项为空),JSF会把FacesContext中的validationFailed标记设为true,同时保留页面上的验证错误消息。
现在看两个a4j:commandLink的差异:
- Calculate按钮(行内):它带有
<f:param>传递行索引,并且位于a4j:region包裹的rich:dataTable行内。当点击它时,a4j:region会限制ajax请求的处理范围,只处理区域内的组件,不会触发区域外输入字段的重新验证。同时,f:param的存在让JSF识别这是一个针对特定行的操作,即使全局验证失败标记为true,也会正常执行action方法。 - Calculate Total按钮(页脚):它没有任何参数,也没有设置跳过验证的属性。当点击它时,ajax请求会尝试执行默认的处理流程:由于全局
validationFailed标记为true,JSF会跳过action方法的执行,直接进入渲染响应阶段。但RichFaces的ajax组件没有正确处理这种“没有新响应内容但验证状态仍为失败”的情况,导致客户端一直卡在“Loading, please wait”状态。
如何修复Calculate Total的问题?
你可以通过以下几种简单的方式解决这个问题,按推荐程度排序:
1. 设置skipValidators="true"(最推荐)
这个属性会让a4j:commandLink的ajax请求跳过所有验证步骤,直接执行action方法。因为Calculate Total操作只需要计算现有列表的总和,不需要依赖表单输入字段的验证状态,所以完全安全:
<a4j:commandLink id="sum_all" styleClass="submit input-submit" action="#{BackingBean.calculateTotalSum}" value="Calculate Total" reRender="itemsTable" skipValidators="true" />
2. 设置immediate="true"
这个属性会让请求直接跳过验证和模型更新阶段,进入应用请求阶段执行action方法。同样适用于Calculate Total这种不需要依赖最新表单输入的操作:
<a4j:commandLink id="sum_all" styleClass="submit input-submit" action="#{BackingBean.calculateTotalSum}" value="Calculate Total" reRender="itemsTable" immediate="true" />
3. 在后台方法中重置验证状态
如果你需要保留页面上的验证消息,可以在calculateTotalSum方法中手动清除validationFailed标记:
public void calculateTotalSum() { // 重置验证失败标记 FacesContext.getCurrentInstance().validationFailed(false); // 执行计算总和的逻辑 // ... }
另外,你提到的替换成h:commandLink加a4j:support的方式之所以能工作,是因为h:commandLink默认会触发整个表单的提交,间接重置了validationFailed标记,但同时也会清除所有验证消息,这就是为什么你会看到验证消息消失的原因。
内容的提问来源于stack exchange,提问作者Armine
相关产品推荐
相关产品推荐

