JSF表单验证使用Ajax卡住

时间:2015-05-04 18:22:23

标签: ajax validation jsf

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

enter image description here

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

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

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

enter image description here

到目前为止很好 - 2大于0.0。直观地,用户然后将放入最大孔直径,该孔直径大于最小值。但表格被卡住了。最小值仍然无效,因为在模型中技术上它仍然是0.0。 Ajax从未在模型中存储值2,但浏览器仍然显示值2.如何才能让2重新验证并存储在我的bean中?

enter image description here

我可以做一次更新=&#34; @ form&#34;将2值清除为零,但这会使用户感到沮丧。如果用户重新输入2,则表单不会被提交,因为它没有更改&#34;。用户必须更改为另一个号码,然后返回2.执行&#34; onblur&#34;也有它的问题。

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

1 个答案:

答案 0 :(得分:1)

这里有几个问题:

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

  2. 默认情况下,<p:ajax>仅处理嵌套的组件,如process="@this"中所示。您确实需要处理其他组件,以便在验证器中具有正确的值。

  3. 更改一个输入时,您没有更新其他输入。因此,当对其进行验证时,其他输入将永远无法删除错误突出显示。

  4. 总而言之,这应该做到:

    <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,或者可以使用它,那么很高兴知道<o:validateOrder>也涵盖了此要求,如下所示(无需任何自定义验证程序) ):

    <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