【问题标题】:JSF Form Validation Using Ajax getting stuck使用 Ajax 的 JSF 表单验证卡住了
【发布时间】:2015-07-14 06:07:57
【问题描述】:

我在一个表单上有两个经过交叉验证的字段。最初用户会看到:

<p:inputText size="5" 
  value="#{bean.maximum_hole_diameter}">
  <f:validator validatorId="doubleNotLessThanSecondDouble" />
  <f:attribute name="secondDouble" 
    value="#{bean.minimum_hole_diameter}" />
  <p:ajax event="change" update="@this" />
</p:inputText>

<p:inputText size="5" 
  value="#{bean.minimum_hole_diameter}">
  <f:validator validatorId="doubleNotGreaterThanSecondDouble" />
  <f:attribute name="secondDouble"
    value="#{bean.maximum_hole_diameter}" />
  <p:ajax event="change" update="@this" />
</p:inputText>

如果用户首先为最大值输入一个正值,然后为最小值输入一个较小的值,则一切都按预期工作。

如果他们首先输入被标记为无效的最小值:

到目前为止一切顺利 - 2 大于 0.0。直观地说,用户会输入一个大于最小值的最大孔径。但是表格卡住了。最小值仍然无效,因为从技术上讲,在模型中它仍然是 0.0。 Ajax 从未将值 2 存储在模型中,但浏览器仍然显示值 2。如何让 2 重新验证并存储在我的 bean 中??

我可以执行 update="@form" 将 2 值清零,但这会让用户感到沮丧。如果用户重新键入 2,则不会提交表单,因为它没有“更改”。用户必须更改为另一个数字,然后返回 2。执行“onblur”也有其问题。

当用户输入 3 时,如何让值 2 重新提交并重新验证?

【问题讨论】:

标签: ajax validation jsf


【解决方案1】:

这里有几个问题:

  1. 您在&lt;f:attribute&gt; 中将模型值而不是组件值传递给验证器。更新的模型值不一定在验证阶段可用,该阶段在更新模型值阶段之前运行。只有在先前的请求中成功处理了引用此模型值的输入字段时,它才会起作用。您最好传递通过binding 引用的物理组件,并在其上使用UIInput#getValue()

  2. &lt;p:ajax&gt; 默认只处理它嵌套的组件,如process="@this"。您确实还需要处理其他组件才能在验证器中获得正确的值。

  3. 更改一个输入时,您并未更新另一个输入。因此,当验证实际成功时,其他输入将永远无法删除错误突出显示。

总而言之,应该这样做:

<p:inputText id="max" binding="#{max}" ...>
    <f:validator validatorId="doubleNotLessThanSecondDouble" />
    <f:attribute name="secondComponent" value="#{min}" />
    <p:ajax process="@this min" update="@this min" />
</p:inputText>

<p:inputText id="min" binding="#{min}" ...>
    <f:validator validatorId="doubleNotGreaterThanSecondDouble" />
    <f:attribute name="secondComponent" value="#{max}" />
    <p:ajax process="@this max" update="@this max" />
</p:inputText>

在这些验证器中使用以下逻辑:

double firstDouble = (double) value;
UIInput secondComponent = (UIInput) component.getAttributes().get("secondComponent");
double secondDouble = (double) secondComponent.getValue();
// ...

另见:


如果您碰巧使用 JSF 实用程序库 OmniFaces,或者愿意使用它,那么很高兴知道 &lt;o:validateOrder&gt; 也涵盖了此要求,如下所示(无需任何自定义验证器):

<h:panelGroup id="diameter">
    <p:inputText id="max" ...>
        <p:ajax process="diameter" update="diameter" />
    </p:inputText>

    <p:inputText id="min" ...>
        <p:ajax process="diameter" update="diameter" />
    </p:inputText>

    <o:validateOrder type="gt" components="max min" />
</h:panelGroup>

与具体问题无关,如果准确性很重要,您最好使用BigDecimal 而不是double

【讨论】:

  • 尝试使用绑定,但 ajax 不会按预期顺序触发验证器。即使我先更改了最小值,最大值的验证器也会首先被触发,然后是最小值的验证器。值与预期不符。
  • 我正在使用 OmniFaces。我实际上查看了omnifaces验证器api并看到了像validateEqual这样的东西。我正在寻找一个 validateGreaterThan。不知道为什么我没有注意到 validateOrder 有 GT、LT 等。将尝试回发
  • 我再次感到惊讶。 validateOrder 就像一个魅力!而且干净多了。
猜你喜欢
  • 2019-11-23
  • 2012-05-14
  • 1970-01-01
  • 2021-02-17
  • 2013-10-19
  • 1970-01-01
  • 1970-01-01
  • 2019-07-15
  • 1970-01-01
相关资源
最近更新 更多