【问题标题】:Why does <o:validateAll> behave different than other validators?为什么 <o:validateAll> 的行为与其他验证器不同?
【发布时间】:2017-02-19 00:39:44
【问题描述】:

我使用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 以查看由 &lt;f:validateDoubleRange&gt; 触发的预期行为:显示面孔消息,并且第一个选项卡仍处于活动状态。

将输入留空并尝试切换到选项卡 2 以查看 &lt;o:validateAll&gt; 的行为:验证似乎失败(显示面孔消息),但选项卡 2 已激活。

更新:所描述的行为适用于switchType="ajax"(默认值)以及switchType="server"。在这两种情况下,选项卡面板都会执行包含的输入的提交,因此从用户的角度来看,选项卡开关似乎与 &lt;h:commandButton&gt; 提交相同(技术上可能存在差异,我不了解tab-panel的实现细节)。

如果我通过带有&lt;f:setPropertyActionListener&gt; 的常规&lt;h:commandButton&gt; 执行制表符切换,&lt;o:validateAll&gt; 的行为方式与其他验证器相同,即由于验证错误而未执行制表符切换。

<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>

注意:这只是一个显示问题行为的简单示例。在我的真实代码中,我不仅有一个由&lt;o:validateAll&gt; 验证的组件,而且我确实将输入值与支持bean 相关联。观察到的行为完全相同。

【问题讨论】:

  • 我刚刚意识到,改变XHTML 代码中&lt;o:validateAll&gt; 标记的位置会改变行为!将它放在应该实际验证的组件之前,它会按预期工作。这是期望的行为还是 OmniFaces 中的错误?文档没有提到这种效果。有什么想法吗?
  • 不确定rich:tabPanel 在幕后的工作原理,但排序行为记录在omnifaces.org/docs/javadoc/2.5/org/omnifaces/component/… 的第一个“一般用法”段落中
  • 对,排序行为已记录在案。但它也说“此验证器可以放置在表单中的任何位置,但请记住,组件将按照它们在表单中出现的顺序进行验证。”。但是,这并没有说明为什么验证会触发周围选项卡面板的不同行为。但也许这里奇怪的是 RichFaces 组件。我的印象是,无论如何,RichFaces 都有更多这样的怪事。也许我会用 PrimeFaces 试试这个例子,看看它是如何工作的。
  • PrimeFaces' &lt;p:tabView&gt; 的行为与 RichFaces 完全不同。 &lt;rich:tabPanel&gt; 在切换到另一个选项卡时提交活动选项卡内的所有输入(当然,在默认的 ajax 模式下)。使用 &lt;p:tabView&gt; 时,输入值不会在服务器上得到处理,直到您将显式 &lt;p:ajax&gt; 添加到输入中。所以恕我直言,这里不可能直接比较。

标签: validation jsf richfaces omnifaces


【解决方案1】:

问题有两个方面。

第一个问题是,&lt;o:validateAll&gt; 不会在验证失败时显式调用 context.renderResponse(),并将此工作留给 JSF,当在 &lt;o:validateAll&gt; 之后发现至少一个输入组件无效时,JSF 将在验证阶段隐式调用它运行,或在后续更新模型值阶段以其他方式运行。

第二个问题是,&lt;rich:tabPanel&gt; 选项卡切换事件在更新模型值阶段而不是在调用应用程序阶段排队。我不确定为什么 RichFaces 的人会这样设计它,但结果是即使仅在更新模型值阶段发现验证失败,也会触发选项卡切换事件。

当您将&lt;o:validateAll&gt; 移动到至少一个关联的输入组件之前,JSF 将在验证阶段已经隐式调用context.renderResponse(),因此完全跳过更新模型值阶段,因此排队的&lt;rich:tabPanel&gt; 选项卡切换事件不会'没有机会被调用。

我已根据issue 322 在 OmniFaces 2.6-SNAPSHOT 中修复它。使用 OmniFaces 2.6 或更高版本时,将 &lt;o:validateAll&gt; 放置在树中的位置不再重要,以实现不调用 &lt;rich:tabPanel&gt; 选项卡切换事件的所需行为。

【讨论】:

  • 感谢您的详细回答,并感谢 OmniFaces 中的修复。
  • 感谢您提出这个问题。
猜你喜欢
  • 2017-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-23
  • 2017-09-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多