我使用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>
触发的预期行为:显示面部消息,并且第一个选项卡仍处于事件状态。将输入留空,然后尝试切换至选项卡2以查看
<o:validateAll>
的行为:验证似乎失败(显示面部消息),但选项卡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>
验证过的组件,而且实际上将输入值与backing-bean相关联。观察到的行为是完全相同的。 最佳答案
这个问题有两个方面。
第一个问题是,验证失败时<o:validateAll>
不会显式调用 context.renderResponse()
,并将此作业留给JSF,它将在验证阶段隐式调用它,前提是在<o:validateAll>
运行之后或者在随后的更新模型中,至少一个输入组件无效时,值(value)观阶段。
第二个问题是,<rich:tabPanel>
选项卡开关事件在更新模型值阶段而不是在调用应用程序阶段排队。我不确定为什么RichFaces会这样设计,但是结果是即使在仅在更新模型值阶段验证失败时,也会触发选项卡切换事件。
当您将<o:validateAll>
移至至少一个关联的输入组件之前时,JSF将已经在验证阶段隐式调用context.renderResponse()
,因此将完全跳过更新模型值阶段,因此排队的<rich:tabPanel>
选项卡切换事件将没有机会被调用。
我已经按照issue 322在OmniFaces 2.6-SNAPSHOT中修复了它。当使用OmniFaces 2.6或更高版本时,将<o:validateAll>
放置在树中的位置不再重要,以便实现不调用<rich:tabPanel>
选项卡开关事件的所需行为。