Java Vaadin 8转换器的行为不同于Vaadin 7转换器(是否更新用户界面)?

Java Vaadin 8转换器的行为不同于Vaadin 7转换器(是否更新用户界面)?,java,converter,vaadin,vaadin7,vaadin8,Java,Converter,Vaadin,Vaadin7,Vaadin8,TL;DR:Vaadin8中是否有类似于Vaadin7的转换器的东西来更新UI中输入字段的表示?即,在输入字段失去焦点后立即从用户输入中删除所有非数字,或将十进制转换为货币 瓦丁论坛链接: 我们目前正在将我们的Vaadin 7项目迁移到Vaadin 8 在我们的Vaadin 7应用程序中,我们有几个转换器。例如,此CurrencyConverter: import java.math.BigDecimal; import java.text.DecimalFormat; import java

TL;DR:Vaadin8中是否有类似于Vaadin7的转换器的东西来更新UI中输入字段的表示?即,在输入字段失去焦点后立即从用户输入中删除所有非数字,或将十进制转换为货币

瓦丁论坛链接:


我们目前正在将我们的Vaadin 7项目迁移到Vaadin 8

在我们的Vaadin 7应用程序中,我们有几个转换器。例如,此CurrencyConverter:

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Locale;
import org.apache.commons.lang3.StringUtils;
import com.vaadin.v7.data.util.converter.StringToBigDecimalConverter;
import com.vaadin.v7.data.util.converter.Converter.ConversionException;

/**
 * A converter that adds/removes the euro sign and
 * formats currencies with two decimal places.
 */
public class EuroConverter extends StringToBigDecimalConverter {

    @Override
    public BigDecimal convertToModel(String value,
                                     Class<? extends BigDecimal> targetType,
                                     Locale locale) throws ConversionException {
        if(StringUtils.isBlank(value)) {
            return null;
        }
        value = value.replaceAll("[€\\s]", "").trim();
        if(StringUtils.isBlank(value)) {
            value = "0";
        }
        return super.convertToModel(value, targetType, locale);
    }

    @Override
    public String convertToPresentation(BigDecimal value,
                                    Class<? extends String> targetType, 
                                    Locale locale) throws ConversionException {
        if(value == null) {
            return null;
        }
        return "€ " + super.convertToPresentation(value, targetType, locale);
    }

    @Override
    protected NumberFormat getFormat(Locale locale) {
        // Always display currency with two decimals
        NumberFormat format = super.getFormat(locale);
        if(format instanceof DecimalFormat) {
            ((DecimalFormat)format).setMaximumFractionDigits(2);
            ((DecimalFormat)format).setMinimumFractionDigits(2);
        }
        return format;
    }
}
TextField inputField = new TextField("Test");
Binder<PiggyBank> binder = new Binder<PiggyBank>();

// PiggyBank only has a property `amount` with getter & setter (see below)
PiggyBank piggyBank = new PiggyBank();
piggyBank.setAmount(BigDecimal.valueOf(1234))

binder.forField(inputField)
      .withConverter(new EuroConverter())
      .bind(PiggyBank::getAmount, PiggyBank::setAmount);
//1
binder.setBean(piggyBank);
//2

addComponent(inputField);
我期望与Vaadin 7中的行为相同,但它的行为如下:

当使用此转换器加载页面时,初始值为
null
,文本字段中不会显示任何内容。如果先前保存的初始值是
“1234”
,则文本字段中将显示
€1.234,00
。这一切都很好。
如果您将此初始值更改为
“987”
,则使用转换器的绑定将在对象中保存“987”,并在您键入文本字段后立即在文本字段中显示
€987,00

它不会更新文本字段中的值。。它仍将显示
987
。似乎Vaadin 8转换器仅用于通过绑定从用户输入到域模型,而不用于更改已输入的内容

另一个变化是,转换器现在放在vaadin8中的绑定本身上,而不是放在vaadin7中的TextField上

下面是一个gif,上面的输入字段显示了我要查找的Vaadin 7/what的行为,下面的输入字段显示了当前Vaadin 8的行为:


编辑:我们尝试过的一些东西:

我创建了一个测试页面,其中只有一个文本字段、一个绑定和一个转换器:

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Locale;
import org.apache.commons.lang3.StringUtils;
import com.vaadin.v7.data.util.converter.StringToBigDecimalConverter;
import com.vaadin.v7.data.util.converter.Converter.ConversionException;

/**
 * A converter that adds/removes the euro sign and
 * formats currencies with two decimal places.
 */
public class EuroConverter extends StringToBigDecimalConverter {

    @Override
    public BigDecimal convertToModel(String value,
                                     Class<? extends BigDecimal> targetType,
                                     Locale locale) throws ConversionException {
        if(StringUtils.isBlank(value)) {
            return null;
        }
        value = value.replaceAll("[€\\s]", "").trim();
        if(StringUtils.isBlank(value)) {
            value = "0";
        }
        return super.convertToModel(value, targetType, locale);
    }

    @Override
    public String convertToPresentation(BigDecimal value,
                                    Class<? extends String> targetType, 
                                    Locale locale) throws ConversionException {
        if(value == null) {
            return null;
        }
        return "€ " + super.convertToPresentation(value, targetType, locale);
    }

    @Override
    protected NumberFormat getFormat(Locale locale) {
        // Always display currency with two decimals
        NumberFormat format = super.getFormat(locale);
        if(format instanceof DecimalFormat) {
            ((DecimalFormat)format).setMaximumFractionDigits(2);
            ((DecimalFormat)format).setMinimumFractionDigits(2);
        }
        return format;
    }
}
TextField inputField = new TextField("Test");
Binder<PiggyBank> binder = new Binder<PiggyBank>();

// PiggyBank only has a property `amount` with getter & setter (see below)
PiggyBank piggyBank = new PiggyBank();
piggyBank.setAmount(BigDecimal.valueOf(1234))

binder.forField(inputField)
      .withConverter(new EuroConverter())
      .bind(PiggyBank::getAmount, PiggyBank::setAmount);
//1
binder.setBean(piggyBank);
//2

addComponent(inputField);
如您所见,每次输入字段值更改时,我们都会读取bean。通过此更改,值仍然正确保存到模型中,并且现在还触发转换器的
convertToPresentation
方法,之后正确显示
€987,00
(尽管在上述编号列表的第2和第3种情况下,它仍然错误地显示
-1.234,00欧元
,而不是
-456,00欧元

我们还尝试了内联lambda转换器,而不是对象;尝试了使用
binder.forMemberField
进行的一些操作;尝试了使用
binder.bindInstanceFields
进行的一些操作;尝试以某种方式检索设置的binder,这是不可能的;等等。我们尝试了各种方法,但Vaadin 8转换器无法正常工作在Vaadin 7中,我们没有找到替代方案,甚至无法找到合适的解决方案


注释中要求的PiggyBank代码:

public class PiggyBank {

    private BigDecimal amount;

    public BigDecimal getAmount() {
        return amount;
    }

    public void setAmount(BigDecimal amount){
        this.amount = amount;
    }
}

此问题已在Vaadin 8.12.1中修复。参考

请将类
储液罐的代码添加到question@petey完成。正如我提到的,它只是一个带有getter和setter的
amount
的类。将编辑
piggyBank.setAmount(1234);
piggyBank.setAmount(bigdecimic.valueOf(1234))
所以,我一直在玩这个,我不得不做一些非常类似的事情。如果这个行为在vaadin 7中起作用(我只在8中),很可能您发现了一个需要报告的bug。@petey感谢您的更正编辑。是的,它确实按照我在Vaadin 7中描述的方式工作。我的同事在Vaadin论坛上问了一个与我类似的问题,但我们都怀疑它确实是一个bug(或者他们故意更改了它,我们无法找出或找到任何关于替代方案的信息。我也很惊讶我在我看到的Vaadin 7到8篇迁移帖子中没有提到这一点。