Browse Source

Fix ValueChangeListener order changes with Binder (#10745)

Fixes #9917
tags/8.4.0.alpha1
Teemu Suo-Anttila 6 years ago
parent
commit
00c3f2c37c

+ 10
- 8
server/src/main/java/com/vaadin/data/Binder.java View File

@@ -982,8 +982,8 @@ public class Binder<BEAN> implements Serializable {

private boolean readOnly;

// Not final since we temporarily remove listener while changing values
private Registration onValueChange;
private final Registration onValueChange;
private boolean valueInit = false;

/**
* Contains all converters and validators chained together in the
@@ -1056,7 +1056,6 @@ public class Binder<BEAN> implements Serializable {
public void unbind() {
if (onValueChange != null) {
onValueChange.remove();
onValueChange = null;
}
binder.removeBindingInternal(this);
binder = null;
@@ -1116,12 +1115,11 @@ public class Binder<BEAN> implements Serializable {
private void initFieldValue(BEAN bean) {
assert bean != null;
assert onValueChange != null;
onValueChange.remove();
valueInit = true;
try {
getField().setValue(convertDataToFieldType(bean));
} finally {
onValueChange = getField()
.addValueChangeListener(this::handleFieldValueChange);
valueInit = false;
}
}

@@ -1139,6 +1137,11 @@ public class Binder<BEAN> implements Serializable {
*/
private void handleFieldValueChange(
ValueChangeEvent<FIELDVALUE> event) {
// Don't handle change events when setting initial value
if (valueInit) {
return;
}

if (binder != null) {
// Inform binder of changes; if setBean: writeIfValid
getBinder().handleFieldValueChange(this, event);
@@ -1180,8 +1183,7 @@ public class Binder<BEAN> implements Serializable {

@Override
public void read(BEAN bean) {
field.setValue(converterValidatorChain.convertToPresentation(
getter.apply(bean), createValueContext()));
getField().setValue(convertDataToFieldType(bean));
}

@Override

+ 25
- 0
server/src/test/java/com/vaadin/data/BinderTest.java View File

@@ -11,6 +11,7 @@ import static org.junit.Assert.assertTrue;

import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;

@@ -1125,4 +1126,28 @@ public class BinderTest extends BinderTestBase<Binder<Person>, Person> {
assertEquals(fiError,
ageField.getErrorMessage().getFormattedHtmlMessage());
}

@Test
public void valueChangeListenerOrder() {
AtomicBoolean beanSet = new AtomicBoolean();
nameField.addValueChangeListener(e -> {
if (!beanSet.get()) {
assertEquals("Value in bean updated earlier than expected",
e.getOldValue(), item.getFirstName());
}
});
binder.bind(nameField, Person::getFirstName, Person::setFirstName);
nameField.addValueChangeListener(e -> {
if (!beanSet.get()) {
assertEquals("Value in bean not updated when expected",
e.getValue(), item.getFirstName());
}
});

beanSet.set(true);
binder.setBean(item);
beanSet.set(false);

nameField.setValue("Foo");
}
}

Loading…
Cancel
Save