我使用OmniFaces' <o:validateAll>验证程序来验证许多输入组件。只要我没有将它放入RichFaces <rich:tabPanel>,这就可以正常工作。当我这样做并将字段留空时,验证失败(如预期的那样),但无论验证失败,活动选项卡都会更改。我试过的其他验证器会阻止tabPanel
在验证失败时切换到另一个选项卡。
这可能是什么原因?
我目前在Wildfly 9.0.2上使用OmniFaces 2.1和RichFaces 4.5.17.Final与Mojarra 2.2.12。
以下是重现问题的XHTML代码:
<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:o="http://omnifaces.org/ui"
xmlns:rich="http://richfaces.org/rich">
<h:form id="form">
<rich:messages />
<rich:tabPanel id="tabPanel">
<rich:tab id="tab1" header="Tab 1">
<h:inputText id="myDouble" value="#{someDoubleVal}">
<f:validateDoubleRange minimum="1.0" maximum="2.0"/>
</h:inputText>
<o:validateAll id="allValid" components="myDouble" message="Missing value!" />
</rich:tab>
<rich:tab id="tab2" header="Tab 2">
Just another tab to switch.
</rich:tab>
</rich:tabPanel>
</h:form>
</ui:composition>
输入1.0和2.0之外的值并尝试切换到标签2以查看由<f:validateDoubleRange>
触发的预期行为:显示faces-message并且第一个标签仍处于活动状态。
将输入留空并尝试切换到选项卡2以查看<o:validateAll>
的行为:验证似乎失败(显示了face-message),但Tab 2已激活。
更新:所述行为适用于switchType="ajax"
(默认)以及switchType="server"
。在这两种情况下,选项卡面板都会执行所包含输入的提交,因此从用户的角度来看,选项卡切换似乎与<h:commandButton>
提交相同(技术上可能存在差异,我不喜欢不知道选项卡面板的实现细节。
如果我通过常规<h:commandButton>
使用<f:setPropertyActionListener>
执行制表符切换,则<o:validateAll>
的行为方式与其他验证程序相同,即制表符切换未执行到期验证错误。
<rich:tabPanel id="tabPanel" activeItem="#{bb.activeTab}">
...
<rich:tab id="tab1" name="tab1" header="Tab 1">
...
<h:commandButton value="submit">
<f:setPropertyActionListener value="tab2" target="#{bb.activeTab}" />
</h:commandButton>
...
</rich:tab>
</rich:tabPanel>
注意:这只是一个显示有问题行为的简约示例。在我的真实代码中,我不只是由<o:validateAll>
验证的单个组件,而且我实际上将输入值与支持bean相关联。观察到的行为完全相同。
答案 0 :(得分:2)
问题是双重的。
第一个问题是,<o:validateAll>
在验证失败时没有显式调用context.renderResponse()
并将此作业留给JSF,这将在验证阶段隐式调用它,此时发现至少一个输入组件无效<o:validateAll>
已在后续更新模型值阶段运行,或以其他方式运行。
第二个问题是,<rich:tabPanel>
制表符切换事件排队等待更新模型值阶段而不是调用应用程序阶段。我不确定RichFaces为什么会这样设计它,但结果是即使在更新模型值阶段发现验证失败时,仍然会触发制表符切换事件。
当您在至少一个关联的输入组件之前移动<o:validateAll>
时,JSF将在验证阶段隐式调用context.renderResponse()
,因此完全跳过更新模型值阶段,因此排队{{1}选项卡切换事件将无法被调用。
我已根据issue 322在OmniFaces 2.6-SNAPSHOT中修复了它。当使用OmniFaces 2.6或更高版本时,为了实现<rich:tabPanel>
制表符切换事件的所需行为不被调用,不应再将<o:validateAll>
置于树中的位置。