TL;DR:在Vaadin8中有类似于Vaadin7的转换器的东西来更新UI中输入字段的表示吗?即。在输入字段失去焦点后立即从用户输入中删除所有非数字,还是将十进制转换为货币?
Vaadin论坛链接:http://Vaadin.com/Forum#!/thread/15931682
我们目前正在将Vaadin7项目迁移到Vaadin8。
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;
}
}
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.data.Result;
import com.vaadin.data.ValueContext;
import com.vaadin.data.converter.StringToBigDecimalConverter;
/**
* A converter that adds/removes the euro sign and formats currencies with two
* decimal places.
*/
public class EuroConverter extends StringToBigDecimalConverter {
public EuroConverter() {
super("defaultErrorMessage");
}
public EuroConverter(String errorMessage) {
super(errorMessage);
}
@Override
public Result<BigDecimal> convertToModel(String value, ValueContext context) {
if(StringUtils.isBlank(value)){
return Result.ok(null);
}
value = value.replaceAll("[€\\s]", "").trim();
if(StringUtils.isBlank(value)){
value = "0";
}
return super.convertToModel(value, context);
}
@Override
public String convertToPresentation(BigDecimal value, ValueContext context) {
if(value == null){
return convertToPresentation(BigDecimal.ZERO, context);
}
return "€ " + super.convertToPresentation(value, context);
}
@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;
}
}
当使用该转换器加载页面时,初始值为null
,它将在TextField中不显示任何内容。如果先前保存的初始值为“1234”
,则会在文本字段中显示1.234,00
。这很好。
如果您将此初始值更改为“987”
,则与转换器的绑定将在对象
中保存“987”,并在键入TextField后立即在TextField
中显示987,00
。
它不更新TextField中的值。它仍将显示987
。Vaadin8转换器似乎只用于通过绑定从用户输入到域模型,而不是用于更改已放入的内容。
另一个变化是,转换器现在放在Vaadin8中的绑定本身上,而不是Vaadin7中的TextField上。
下面是一个gif,上面的输入字段是Vaadin7/what的行为,下面的输入字段是当前的Vaadin8的行为:
编辑:我们尝试过的一些操作:
我创建了一个只有一个TextField、一个绑定和一个转换器的测试页面:
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);
一些需要注意的事情:
piggybank.setamount(456);
,它将首先在UI的TextField中显示456,00
。piggybank.setamount(456);
,它仍然会在UI的TextField中显示1.234,00
!因此在binder.setBean(piggyBank)
converttopresentation
方法就不再被触发了
piggyBank.setamount(456);
,并删除binder.setbean(piggyBank);
,它仍然显示1.234,00
而不是456,00
!我们已经能够找到一个难看的变通办法,它是这样的:
inputField.setValueChangeMode(ValueChangeMode.BLUR);
inputField.addBlurListener(new BlurListener() {
@Override
public void blur(BlurEvent event) {
if(binder.isValid()) {
binder.readBean(binder.getBean());
}
}
});
正如您所看到的,我们只是在每次输入字段值改变时读取bean。通过此更改,该值仍然正确地保存到模型中,并且现在还触发转换器的converttopresentation
方法,在此之后正确地显示987,00
(尽管在上面编号列表的情况2和3中仍然错误地显示1.234,00
,而不是456,00
)。
我们也尝试过内联lambda转换器而不是对象;尝试使用binder.formemberfield
;尝试使用binder.bindinstancefields
;试图以某种方式检索设置的活页夹,这是不可能的;等等,我们已经尝试了所有的方法,但是Vaadin8转换器不像在Vaadin7中那样工作,我们无法找到一个替代的甚至是适当的解决方案。
备注中的储蓄罐代码:
public class PiggyBank {
private BigDecimal amount;
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount){
this.amount = amount;
}
}
此问题已在Vaadin 8.12.1中修复。裁判。https://github.com/vaadin/framework/pull/12132
获取以下错误: 请帮我把结果设置到这个BO类中。
我试图在java中实现不同类型之间的转换器:我有一个超级类foo,有2个子类: fo1和fo2,我也有2个不相关的其他类bar1和bar2,我试图实现一个转换器从bar1到fo1和bar2to fo2(与之相反)。 因为我在这里有继承,所以我想应该创建一个泛型类型的接口(将是bar1或bar2),它将定义转换所需的函数,我还想让转换器成为bar1和bar2的通用转换器,我认为它应该以某种方式使用接
我正试图从Netsuite中获取数据,并使用Mulesoft Dataweave元素和when将其保存到salesforce对象中,否则,请参见下面的代码片段,但给出了错误: 找不到将“SimpleDataType{type=java.util.LinkedHashMap,mimetype='/',encoding='null'}”转换为“CollectionDataType{type=java.
考虑下面这个简短的C++程序: 如果我在不同的编译器上编译它,我会得到不同的结果。对于CLANG3.4和GCC 4.4.7,它打印,而Visual Studio 2013打印,这意味着它们在调用不同的强制转换操作符。根据标准,哪一个是正确的行为? 根据我的理解,不需要转换,而需要到的转换,因此编译器应该选择第一个。对此做了什么吗?const-conversion是否被编译器认为更“昂贵”? 如果删
最近我读到了关于运算符执行的智能强制转换,以及关于或更好的运算符用于显式强制转换。 kotlin docs的种类及其使用差异如下:- 请注意,当编译器无法保证变量不能在检查和使用之间更改时,智能强制转换不起作用。更具体地说,智能强制转换根据以下规则适用: > val局部变量-始终不包括局部委托属性; val属性-如果属性是私有的或内部的,或者检查是在声明属性的同一模块中执行的。智能强制转换不适用于
我使用ModelMapper将一些对象转换为复杂的DTO,反之亦然。 尽管我试图理解留档,但我发现很难理解何时使用转换器、提供程序或抽象转换器。 现在,例如,如果我想将字符串属性转换为目标DTO中的小DTO,我将在抽象转换器中手动执行。 例如: 虽然这是正确的方法吗?我应该何时使用提供商? 如果我想用条件设置属性,我可以在转换器中使用条件吗?或者只有在使用PropertyMap时才能使用条件? 此