Browse Source

Binder: Also use converter for user-changed values (#12132)

See: https://vaadin.com/forum/thread/15931682
tags/7.7.23
Tatu Lund 3 years ago
parent
commit
5c839bc683
No account linked to committer's email address

+ 9
- 1
server/src/main/java/com/vaadin/data/Binder.java View 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);
}

+ 65
- 0
server/src/test/java/com/vaadin/data/BinderTest.java View 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;
}
}
}

Loading…
Cancel
Save