From: Tatu Lund Date: Thu, 3 Dec 2020 03:27:30 +0000 (+0200) Subject: Binder: Also use converter for user-changed values (#12132) X-Git-Tag: 7.7.23~9 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=5c839bc6837b90d72561f3a478c0d6089a8f17ba;p=vaadin-framework.git Binder: Also use converter for user-changed values (#12132) See: https://vaadin.com/forum/thread/15931682 --- diff --git a/server/src/main/java/com/vaadin/data/Binder.java b/server/src/main/java/com/vaadin/data/Binder.java index d0ea628986..481b6df361 100644 --- a/server/src/main/java/com/vaadin/data/Binder.java +++ b/server/src/main/java/com/vaadin/data/Binder.java @@ -1282,7 +1282,15 @@ public class Binder implements Serializable { Result result = doConversion(); if (!isReadOnly()) { - result.ifOk(value -> setter.accept(bean, value)); + result.ifOk(value -> { + setter.accept(bean, value); + if (value != null) { + FIELDVALUE converted = convertToFieldType(value); + if (!field.getValue().equals(converted)) { + getField().setValue(converted); + } + } + }); } return toValidationStatus(result); } diff --git a/server/src/test/java/com/vaadin/data/BinderTest.java b/server/src/test/java/com/vaadin/data/BinderTest.java index b64dee9c6b..0332572203 100644 --- a/server/src/test/java/com/vaadin/data/BinderTest.java +++ b/server/src/test/java/com/vaadin/data/BinderTest.java @@ -10,6 +10,9 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.math.BigDecimal; +import java.text.DecimalFormat; +import java.text.NumberFormat; import java.util.Locale; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; @@ -25,6 +28,7 @@ import org.junit.rules.ExpectedException; import com.vaadin.data.Binder.Binding; import com.vaadin.data.Binder.BindingBuilder; +import com.vaadin.data.converter.StringToBigDecimalConverter; import com.vaadin.data.converter.StringToIntegerConverter; import com.vaadin.data.validator.IntegerRangeValidator; import com.vaadin.data.validator.NotEmptyValidator; @@ -500,6 +504,19 @@ public class BinderTest extends BinderTestBase, Person> { assertEquals(11, salary.intValue()); } + @Test + public void withConverter_writeBackValue() { + TextField rentField = new TextField(); + rentField.setValue(""); + binder.forField(rentField).withConverter(new EuroConverter("")) + .withNullRepresentation(BigDecimal.valueOf(0d)) + .bind(Person::getRent, Person::setRent); + binder.setBean(item); + rentField.setValue("10"); + + assertEquals("€ 10.00", rentField.getValue()); + } + @Test public void beanBinder_nullRepresentationIsNotDisabled() { Binder binder = new Binder<>(Person.class); @@ -1483,4 +1500,52 @@ public class BinderTest extends BinderTestBase, Person> { .bind(AtomicReference::get, AtomicReference::set); return binder; } + + /** + * 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 convertToModel(String value, + ValueContext context) { + if (value.isEmpty()) { + return Result.ok(null); + } + value = value.replaceAll("[€\\s]", "").trim(); + if (value.isEmpty()) { + 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; + } + } }