【发布时间】:2017-04-12 08:28:20
【问题描述】:
我有一个 JSF 2.2 应用程序,用户必须在 <h:inputText> 中输入 BigDecimal 值。对于这样的输入字段,valueChangeListener 配置为在输入更改时调用。这是 XHTML 代码:
<h:form id="theForm">
<h:inputText id="bd" value="#{bean.bd}"
valueChangeListener="#{bean.bdChangedListener()}"/>
<h:commandButton id="submit" value="Submit" />
</h:form>
这在大多数情况下都可以正常工作。 bdChangedListener() 方法被调用,当值改变并且提交按钮被按下时。该值已正确提交给模型。
但是,如果我输入1.1 并将其更改为1.10,新值将提交给模型,但valueChangeListener 是从不调用!调试显示,原因在于javax.faces.component.UIInput#compareValues()。 JavaDoc 来自
this method 说:
如果新值与之前的值不同,则返回 true。 首先通过将 value 传递给 equals 方法来比较两个值 论据前。如果该方法返回 true,则返回 true。如果说 方法返回 false,并且两个参数都实现 java.lang.Comparable,通过传递值来比较两个值 compareTo 方法上的参数先前。如果此方法返回 true 返回 0,否则返回 false。
所以在我看来,这是故意的。但为什么呢?
用户输入发生了变化,并且存在与BigDecimal 的比例相关的应用程序。所以 JSF 不应该只是忽略更改的输入,而是通知我!它用新值更新模型,为什么会跳过 valueChangeListener 方法?
我怎样才能避免这种行为并以干净的方式获得通知? (我知道我可以挂钩到二传手,但这不是我所说的干净的方式!)
有什么想法吗?
进一步阅读和cmets
除了上面我想提到的,我已经阅读过BigDecimal equals() versus compareTo() 之类的问题。我确实理解为什么 BigDecimal 的 equals() 和 compareTo() 表现得像他们一样,我会说这是正确的。 BigDecimal 的行为不是问题,UIInput.compareValues() 是问题。
此外,转换器(如 cmets 中的建议或已删除的答案)也无法挽救我的一天。用户输入已正确转换,我需要 BidDecimal,包括我的应用程序中的确切比例。任何返回 BigDecimal 的转换器都不会改变观察到的行为。
围绕 BigDecimal 的包装类可能会解决我的问题,但不是我认为的干净的解决方案。我真的很想知道为什么 UIInput 的行为方式如此。
【问题讨论】:
-
抱歉,1.1 和 1.10 是相等的。这只是格式更改而不是值。
-
数字可能相等,但 BigDecimal 对象不相等。为什么 equals() 否则会返回 false?在某些情况下,实际 BigDecimal 的规模很重要。这不仅与格式有关,而且与计算有关,这可能会根据实际规模给出不同的结果。
-
@MartinHöller 但是值是相等的,它是一个
ValueChangeListener。 -
@EJP 现在我们越来越哲学了 ;-)
<h:input>的价值是什么? BigDecimal 对象还是它所代表的数字?但我明白了你的意思,这可能确实是观察到的行为的原因。我仍然觉得这很不直观。 -
@Downvoter 请告诉我你为什么不赞成这个问题。否则我无法为未来学习。
标签: jsf