From a91d5043994f92f64b77f70ab21a56bacc2ab675 Mon Sep 17 00:00:00 2001 From: knoobie Date: Wed, 24 Mar 2021 10:52:53 +0100 Subject: [PATCH] fix: Add API to control whether Binder converts back to presentation (CP: #10343) --- .../com/vaadin/flow/data/binder/Binder.java | 58 ++++++++++++++++++- .../vaadin/flow/data/binder/BinderTest.java | 17 +++++- 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/flow-data/src/main/java/com/vaadin/flow/data/binder/Binder.java b/flow-data/src/main/java/com/vaadin/flow/data/binder/Binder.java index 225fa7197fb..f41950b5f8d 100644 --- a/flow-data/src/main/java/com/vaadin/flow/data/binder/Binder.java +++ b/flow-data/src/main/java/com/vaadin/flow/data/binder/Binder.java @@ -250,6 +250,32 @@ default BindingValidationStatus validate() { * @return A boolean value. */ public boolean isValidatorsDisabled(); + + /** + * Define whether the value should be converted back to the presentation + * in the field when a converter is used in binding. + *

+ * As of version 6.0, when a converter is used on a binding and the user + * input value is modified by the converter, the value from the converter + * is applied back to the input. It is possible to control this behavior + * with this API. + * + * @see BindingBuilder#withConverter(Converter) + * @see BindingBuilder#withConverter(SerializableFunction, SerializableFunction) + * @see BindingBuilder#withConverter(SerializableFunction, SerializableFunction, String) + * + * @param convertBackToPresentation + * A boolean value + */ + void setConvertBackToPresentation(boolean convertBackToPresentation); + + /** + * Returns whether the value is converted back to the presentation in + * the field when a converter is used in binding. + * + * @return A boolean value + */ + boolean isConvertBackToPresentation(); } /** @@ -508,6 +534,12 @@ default BindingBuilder withValidator( * For instance, a {@code TextField} can be bound to an integer-typed * property using an appropriate converter such as a * {@link StringToIntegerConverter}. + *

+ * The converted value is applied back to the field by default, + * this can be controlled with the method + * {@link Binding#setConvertBackToPresentation(boolean)}. + * + * @see Binding#setConvertBackToPresentation(boolean) * * @param * the type to convert to @@ -534,6 +566,12 @@ BindingBuilder withConverter( * For instance, a {@code TextField} can be bound to an integer-typed * property using appropriate functions such as: * withConverter(Integer::valueOf, String::valueOf); + *

+ * The converted value is applied back to the field by default, + * this can be controlled with the method + * {@link Binding#setConvertBackToPresentation(boolean)}. + * + * @see Binding#setConvertBackToPresentation(boolean) * * @param * the type to convert to @@ -569,6 +607,12 @@ default BindingBuilder withConverter( * For instance, a {@code TextField} can be bound to an integer-typed * property using appropriate functions such as: * withConverter(Integer::valueOf, String::valueOf); + *

+ * The converted value is applied back to the field by default, + * this can be controlled with the method + * {@link Binding#setConvertBackToPresentation(boolean)}. + * + * @see Binding#setConvertBackToPresentation(boolean) * * @param * the type to convert to @@ -1055,6 +1099,8 @@ protected static class BindingImpl private boolean validatorsDisabled = false; + private boolean convertBackToPresentation = true; + public BindingImpl(BindingBuilderImpl builder, ValueProvider getter, Setter setter) { @@ -1246,7 +1292,7 @@ private BindingValidationStatus writeFieldValue(BEAN bean) { if (!isReadOnly()) { result.ifOk(value -> { setter.accept(bean, value); - if (value != null) { + if (convertBackToPresentation && value != null) { FIELDVALUE converted = convertToFieldType(value); if (!field.getValue().equals(converted)) { getField().setValue(converted); @@ -1353,6 +1399,16 @@ public void setValidatorsDisabled(boolean validatorsDisabled) { public boolean isValidatorsDisabled() { return validatorsDisabled; } + + @Override + public void setConvertBackToPresentation(boolean convertBackToPresentation) { + this.convertBackToPresentation = convertBackToPresentation; + } + + @Override + public boolean isConvertBackToPresentation() { + return convertBackToPresentation; + } } /** diff --git a/flow-data/src/test/java/com/vaadin/flow/data/binder/BinderTest.java b/flow-data/src/test/java/com/vaadin/flow/data/binder/BinderTest.java index 357724bf70e..73a3a60c92b 100644 --- a/flow-data/src/test/java/com/vaadin/flow/data/binder/BinderTest.java +++ b/flow-data/src/test/java/com/vaadin/flow/data/binder/BinderTest.java @@ -583,7 +583,22 @@ public void withConverter_writeBackValue() { // € 10.00 assertEquals("€ " + new DecimalFormat("0.00").format(10), rentField.getValue()); - } + } + + @Test + public void withConverter_writeBackValueDisabled() { + TestTextField rentField = new TestTextField(); + rentField.setValue(""); + Binding binding = binder.forField(rentField) + .withConverter(new EuroConverter("")) + .withNullRepresentation(BigDecimal.valueOf(0d)) + .bind(Person::getRent, Person::setRent); + binder.setBean(item); + binding.setConvertBackToPresentation(false); + rentField.setValue("10"); + + assertNotEquals("€ 10.00", rentField.getValue()); + } @Test public void beanBinder_nullRepresentationIsNotDisabled() {