如果仅更改了比例,则不会调用BigDecimal值的ValueChangeListener

Mar*_*ler 10 jsf

我有一个JSF 2.2应用程序,用户必须输入BigDecimal<h:inputText>.对于这样的输入字段,a valueChangeListener被配置为在输入变化时被调用.这是XHTML代码:

<h:form id="theForm">
  <h:inputText id="bd" value="#{bean.bd}"
               valueChangeListener="#{bean.bdChangedListener()}"/>
  <h:commandButton id="submit" value="Submit" />
</h:form>
Run Code Online (Sandbox Code Playgroud)

在大多数情况下,这样做很好.bdChangedListener()当值改变并按下提交按钮时,将调用该方法.该值已正确提交给模型.

但是,如果我进入1.1并改变它1.10,新的值被提交到模型,但valueChangeListener从来没有所谓!Debuging表明,其原因在于javax.faces.component.UIInput#compareValues().这种方法的JavaDoc 说:

如果新值与先前值不同,则返回true.首先通过将值传递给参数previous之前的equals方法来比较这两个值.如果该方法返回true,则返回true.如果该方法返回false,并且两个参数都实现java.lang.Comparable,则通过将值传递给参数previous之前的compareTo方法来比较这两个值.如果此方法返回0,则返回true,否则返回false.

所以在我看来,这是故意的.但为什么?

用户输入已更改,并且存在应用程序,其中a的比例BigDecimal是相关的.所以JSF不应该忽略改变的输入,而是通知我!它使用新值更新模型,为什么它会跳过valueChangeListener-method?

我怎样才能避免这种行为并以干净的方式得到通知?(我知道我可以挂进制定者,但这不是我所谓的干净方式!)

有任何想法吗?

进一步阅读和评论

除了上面我想提到的,我已经读过像BigDecimal equals()和compareTo()这样的问题.我确实理解为什么BigDecimal equals()compareTo()他们的行为一样,我说它是正确的.BigDecimal的行为不是问题,UIInput.compareValues()而是问题.

此外,转换器(如评论或已删除的答案中所示)将无法保存我的一天.用户输入已正确转换,我需要BidDecimal,包括我的应用程序中的确切比例.任何返回BigDecimal的转换器都不会改变观察到的行为.

围绕BigDecimal的包装类可能会解决我的问题,但不是我认为的干净解决方案.我真的想知道为什么UIInput的行为方式.

Bal*_*usC 4

它确实按照指定的方式运行。就是这样。您已经非常正确地确定了根本原因javax.faces.component.UIInput#compareValues()。解决方案是让它跳过额外的Comparable#compareTo()检查。

您最好的选择是相应地扩展HtmlInputText并覆盖compareValues()

@FacesComponent(createTag=true)
public class InputBigDecimal extends HtmlInputText {

    @Override
    protected boolean compareValues(Object previous, Object value) {
        return !Objects.equals(previous, value);
    }

}
Run Code Online (Sandbox Code Playgroud)

然后只需替换<h:inputText><x:inputBigDecimal>如下所示。

<... xmlns:x="http://xmlns.jcp.org/jsf/component">
...
<h:form id="theForm">
    <x:inputBigDecimal id="bd" value="#{bean.bd}"
                       valueChangeListener="#{bean.bdChangedListener()}" />
    <h:commandButton id="submit" value="Submit" />
</h:form>
Run Code Online (Sandbox Code Playgroud)

注意:代码按原样完整。由于 JSF 2.2 的createTag=true. 您只会错过 IDE 的 XML 智能感知,但这是一个不同的问题。