为什么 <o:validateAll> 的行为与其他验证器不同?
Why does <o:validateAll> behave different than other validators?
我用OmniFaces' <o:validateAll> validator to validate a number of input components. This works fine as long as I do not put it into a 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>
提交相同(技术上可能存在差异,我不不知道选项卡面板的实现细节)。
如果我通过带有 <f:setPropertyActionListener>
的常规 <h:commandButton>
执行制表符切换,<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 相关联。观察到的行为完全相同。
问题有两个。
第一个问题是,<o:validateAll>
不会在验证失败时显式调用 context.renderResponse()
并将此工作留给 JSF,JSF 将在验证阶段至少找到一个输入组件时隐式调用它在 <o:validateAll>
具有 运行 之后无效,否则在后续更新模型值阶段无效。
第二个问题是,<rich:tabPanel>
选项卡切换事件排队等待更新模型值阶段而不是调用应用程序阶段。我不确定为什么 RichFaces 的人会那样设计它,但结果是即使仅在更新模型值阶段发现验证失败,标签切换事件仍然会被触发。
当您将 <o:validateAll>
移动到至少一个关联的输入组件之前时,JSF 将在验证阶段隐式调用 context.renderResponse()
并因此完全跳过更新模型值阶段以及排队的 <rich:tabPanel>
选项卡切换事件将没有机会被调用。
我已根据 issue 322 在 OmniFaces 2.6-SNAPSHOT 中修复它。当使用 OmniFaces 2.6 或更新版本时,<o:validateAll>
放置在树中的哪个位置以实现不调用 <rich:tabPanel>
选项卡切换事件的预期行为不再重要。
我用OmniFaces' <o:validateAll> validator to validate a number of input components. This works fine as long as I do not put it into a 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>
提交相同(技术上可能存在差异,我不不知道选项卡面板的实现细节)。
如果我通过带有 <f:setPropertyActionListener>
的常规 <h:commandButton>
执行制表符切换,<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 相关联。观察到的行为完全相同。
问题有两个。
第一个问题是,<o:validateAll>
不会在验证失败时显式调用 context.renderResponse()
并将此工作留给 JSF,JSF 将在验证阶段至少找到一个输入组件时隐式调用它在 <o:validateAll>
具有 运行 之后无效,否则在后续更新模型值阶段无效。
第二个问题是,<rich:tabPanel>
选项卡切换事件排队等待更新模型值阶段而不是调用应用程序阶段。我不确定为什么 RichFaces 的人会那样设计它,但结果是即使仅在更新模型值阶段发现验证失败,标签切换事件仍然会被触发。
当您将 <o:validateAll>
移动到至少一个关联的输入组件之前时,JSF 将在验证阶段隐式调用 context.renderResponse()
并因此完全跳过更新模型值阶段以及排队的 <rich:tabPanel>
选项卡切换事件将没有机会被调用。
我已根据 issue 322 在 OmniFaces 2.6-SNAPSHOT 中修复它。当使用 OmniFaces 2.6 或更新版本时,<o:validateAll>
放置在树中的哪个位置以实现不调用 <rich:tabPanel>
选项卡切换事件的预期行为不再重要。