]> source.dussan.org Git - vaadin-framework.git/commitdiff
Binder: Also use converter for user-changed values (#12132)
authorTatu Lund <tatu@vaadin.com>
Thu, 3 Dec 2020 03:27:30 +0000 (05:27 +0200)
committerGitHub <noreply@github.com>
Thu, 3 Dec 2020 03:27:30 +0000 (05:27 +0200)
See: https://vaadin.com/forum/thread/15931682

server/src/main/java/com/vaadin/data/Binder.java
server/src/test/java/com/vaadin/data/BinderTest.java

index d0ea6289867bc5db15ebd5508adbbb0ee2920a75..481b6df3617fcfb5b0ce1a62a21744bd72a972f9 100644 (file)
@@ -1282,7 +1282,15 @@ public class Binder<BEAN> implements Serializable {
 
             Result<TARGET> 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);
         }
index b64dee9c6b367eedc5457f1fb13e89f97ebe37d2..03325722031dca212c2968ccb784f15e7e7da502 100644 (file)
@@ -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<Binder<Person>, 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<Person> binder = new Binder<>(Person.class);
@@ -1483,4 +1500,52 @@ public class BinderTest extends BinderTestBase<Binder<Person>, 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<BigDecimal> 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;
+        }
+    }
 }