当前位置: 首页 > 知识库问答 >
问题:

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

汪鸿波
2023-03-14

我有一个JSF2.2应用程序,用户必须在

<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,则新值将提交给模型,但从未调用值更改侦听器!调试表明,原因在于javax。面孔。组成部分UIInput#compareValues()。此方法的JavaDoc表示:

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

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

用户输入发生了变化,有些应用程序与bigdecimic的比例相关。所以JSF不应该忽略更改的输入,而是通知我!它用新值更新模型,为什么要跳过valueChangeListener方法?

我怎样才能避免这种行为,并以干净的方式得到通知?(我知道我可以打二传,但这不是我所说的干净的方式!)

有什么想法吗?

除了上面我想提到的,我已经读了像BigDecimal equals()和compareTo()这样的问题。我确实理解为什么BigDecimal的equals()compareTo()表现得像他们一样,我认为这是正确的。BigDecimal的行为不是问题所在,UIInput.compare值()才是问题所在。

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

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

共有2个答案

窦夜洛
2023-03-14

BalusC的回答描述了一种通用的方法,在不改变应用程序行为的情况下以一种干净的方式解决问题。可能的解决方法是使用AJAX-listener,而不是value eChangeListener

<h:form id="theForm">
  <h:inputText id="bd" value="#{bean.bd}">
    <f:ajax listener="#{bean.ajaxListener}"/>
  </h:inputText>
  <h:commandButton id="submit" value="Submit" />
</h:form>

侦听器方法必须具有不同的签名:

public void ajaxListener(AjaxBehaviorEvent event)
{
    // Do whatever you like here.
    // The new value is already in the model.
}

请注意,只要触发DOM更改事件(而不是按下sumbit按钮),就会调用AJAX侦听器,并且不会像valueChangeListener那样检查实际值是否更改。

关于这两种方法的差异,可以在BalusC关于何时使用valueChangeListener或f:ajax listener?的出色回答中找到详细信息?。

龙弘济
2023-03-14

它的行为确实符合规定。事实就是这样。您已经非常正确地确定了javax的根本原因。面孔。组成部分UIInput#compareValues()。解决方案是让它跳过额外的Comparable#compareTo()检查。

最好的办法是扩展HtmlInputText并相应地覆盖compareVales()

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

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

}

然后只需更换

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

注意:代码是完整的。由于JSF 2.2的createTag=true,不需要额外的XML配置文件。在这方面,您只会错过IDE的XML智能,但这是一个不同的问题。

 类似资料:
  • 问题内容: 是否可以在sql中执行更新语句,但仅在更新不同时才执行更新? 例如 如果在数据库中, 不应 执行任何类型的更新 但是,如果 这 应该 执行更新。 问题答案: 使用更新前触发器可以做到这一点。在此触发器中,您可以将旧值与新值进行比较,并在新值不变的情况下取消更新。但这将导致呼叫者网站上的错误。 我不知道为什么要这样做,但是这里有几种可能性: 性能:这里没有性能提升,因为更新不仅需要找到正

  • 以下是我需要更改的一些值: 如果第一列是2= 如果第一列是8= 如果第一列是16= 然而,这个命令并不方便,因为它改变了缩进,并且带有8的行似乎不适合: 输出: 您将如何更正更通用的内容(这意味着即使特定行的缩进不同,它也可以工作),并且不会改变原始文件的缩进?

  • 问题内容: 我有一个字段的最小值取决于另一字段中给定的输入的要求。 此输入用于验证另一个字段 但这不能按预期工作..如果我以后更改“ minval”,则输入不会得到重新验证。 我已经尝试根据一些解决方案中的建议从JS设置min的初始值,但这也无济于事… 链接器 问题答案: 使用ng-min / ng-max指令

  • 我想使用JavaFX ListView控件显示一个人员列表(在POJOS中编码,包含一个name和surname属性)。我创建了ListView,并将persons列表添加为ObservableList。如果我在ObservableList中删除或添加一个新人,那么一切都可以正常工作,但是POJO中的更改不会触发ListView的更新。我必须从ObservableList中移除和添加修改后的POJ

  • SQL架构: 我需要这样显示我的结果: 结果显示表SNMASTER的前5行 然后查看表事务,并在有OPERATION_ID时写入1

  • 我正在做一个数据密集的角度项目,在这个项目中,我有一个ng重复,其中许多值每秒更新一次。如果一个值为空,它现在会更新DOM以显示一个空值;这是正确的行为。 需要的解决方案 我想要的是一个过滤器或表达式,当新值为空或NULL时,它不会更新DOM中的值。我相信他们称之为“锁定数据”。 可能的解决方案 我用$watch找到了几个可能的解决方案,但我相信它们不适合ng重复,或者至少效率不高:angular