我在表单上有两个交叉验证的字段。最初用户看到:
<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中?
我可以做一次更新=&#34; @ form&#34;将2值清除为零,但这会使用户感到沮丧。如果用户重新输入2,则表单不会被提交,因为它没有更改&#34;。用户必须更改为另一个号码,然后返回2.执行&#34; onblur&#34;也有它的问题。
当用户输入3时,如何获取值2以重新提交并重新验证?
答案 0 :(得分:1)
这里有几个问题:
您正在<f:attribute>
将模型值传递给验证程序而不是组件值。验证阶段不一定可以使用更新的模型值,验证阶段在更新模型值阶段之前运行。只有在先前的请求中成功处理了引用此模型值的输入字段时,它才会起作用。您最好通过binding
引用的物理组件,并在其上使用UIInput#getValue()
。
默认情况下,<p:ajax>
仅处理嵌套的组件,如process="@this"
中所示。您确实需要处理其他组件,以便在验证器中具有正确的值。
更改一个输入时,您没有更新其他输入。因此,当对其进行验证时,其他输入将永远无法删除错误突出显示。
总而言之,这应该做到:
<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
。