Change-Id: I2121ec8f90ffcdf2fdfa02bf99084b539b27180etags/8.0.0.alpha1
@@ -485,6 +485,7 @@ public class Binder<BEAN> implements Serializable { | |||
FIELDVALUE fieldValue = field.getValue(); | |||
Result<TARGET> dataValue = converterValidatorChain.convertToModel( | |||
fieldValue, ((AbstractComponent) field).getLocale()); | |||
fireStatusChangeEvent(dataValue); | |||
return dataValue; | |||
} | |||
@@ -554,7 +555,7 @@ public class Binder<BEAN> implements Serializable { | |||
return newBinding; | |||
} | |||
private void fireStatusChangeEvent(Result<?> result) { | |||
private void fireStatusChangeEvent(Result<TARGET> result) { | |||
ValidationStatusChangeEvent event = new ValidationStatusChangeEvent( | |||
getField(), | |||
result.isError() ? ValidationStatus.ERROR | |||
@@ -716,7 +717,6 @@ public class Binder<BEAN> implements Serializable { | |||
List<ValidationError<?>> resultErrors = new ArrayList<>(); | |||
for (BindingImpl<BEAN, ?, ?> binding : bindings) { | |||
Result<?> result = binding.validate(); | |||
binding.fireStatusChangeEvent(result); | |||
result.ifError(errorMessage -> resultErrors | |||
.add(new ValidationError<>(binding.field, errorMessage))); | |||
} |
@@ -256,7 +256,7 @@ public class BinderBookOfVaadinTest { | |||
} | |||
@Test | |||
public void crossFieldValidation() { | |||
public void crossFieldValidation_validateUsingBinder() { | |||
Binder<Trip> binder = new Binder<>(); | |||
PopupDateField departing = new PopupDateField("Departing"); | |||
PopupDateField returning = new PopupDateField("Returning"); | |||
@@ -310,6 +310,56 @@ public class BinderBookOfVaadinTest { | |||
} | |||
@Test | |||
public void crossFieldValidation_validateUsingBinding() { | |||
Binder<Trip> binder = new Binder<>(); | |||
PopupDateField departing = new PopupDateField("Departing"); | |||
PopupDateField returning = new PopupDateField("Returning"); | |||
Binding<Trip, Date, Date> returnBinding = binder.forField(returning) | |||
.withValidator( | |||
returnDate -> !returnDate.before(departing.getValue()), | |||
"Cannot return before departing"); | |||
returnBinding.bind(Trip::getReturnDate, Trip::setReturnDate); | |||
departing.addValueChangeListener(event -> returnBinding.validate()); | |||
Calendar calendar = Calendar.getInstance(); | |||
Date past = calendar.getTime(); | |||
calendar.add(1, Calendar.DAY_OF_YEAR); | |||
Date before = calendar.getTime(); | |||
calendar.add(1, Calendar.DAY_OF_YEAR); | |||
Date after = calendar.getTime(); | |||
departing.setValue(before); | |||
returning.setValue(after); | |||
Result<Date> result = returnBinding.validate(); | |||
Assert.assertFalse(result.isError()); | |||
Assert.assertNull(departing.getComponentError()); | |||
// update returning => validation is done against this field | |||
returning.setValue(past); | |||
result = returnBinding.validate(); | |||
Assert.assertTrue(result.isError()); | |||
Assert.assertNotNull(returning.getComponentError()); | |||
// set correct value back | |||
returning.setValue(before); | |||
result = returnBinding.validate(); | |||
Assert.assertFalse(result.isError()); | |||
Assert.assertNull(departing.getComponentError()); | |||
// update departing => validation is done because of listener added | |||
departing.setValue(after); | |||
result = returnBinding.validate(); | |||
Assert.assertTrue(result.isError()); | |||
Assert.assertNotNull(returning.getComponentError()); | |||
} | |||
@Test | |||
public void withStatusLabelExample() { | |||
Label emailStatus = new Label(); |
@@ -460,6 +460,25 @@ public class BinderTest { | |||
Assert.assertNull(nameField.getComponentError()); | |||
} | |||
@Test | |||
public void bindingWithStatusChangeHandler_defaultStatusChangeHandlerIsReplaced() { | |||
Binding<Person, String, String> binding = binder.forField(nameField) | |||
.withValidator(notEmpty).withStatusChangeHandler(evt -> { | |||
}); | |||
binding.bind(Person::getFirstName, Person::setLastName); | |||
Assert.assertNull(nameField.getComponentError()); | |||
nameField.setValue(""); | |||
// First validation fails => should be event with ERROR status and | |||
// message | |||
binding.validate(); | |||
// default behavior should update component error for the nameField | |||
Assert.assertNull(nameField.getComponentError()); | |||
} | |||
@Test | |||
public void withStatusLabel_labelIsUpdatedAccordingStatus() { | |||
Label label = new Label(); | |||
@@ -487,6 +506,33 @@ public class BinderTest { | |||
Assert.assertEquals("", label.getValue()); | |||
} | |||
@Test | |||
public void bindingWithStatusLabel_labelIsUpdatedAccordingStatus() { | |||
Label label = new Label(); | |||
Binding<Person, String, String> binding = binder.forField(nameField) | |||
.withValidator(notEmpty).withStatusLabel(label); | |||
binding.bind(Person::getFirstName, Person::setLastName); | |||
nameField.setValue(""); | |||
// First validation fails => should be event with ERROR status and | |||
// message | |||
binding.validate(); | |||
Assert.assertTrue(label.isVisible()); | |||
Assert.assertEquals("Value cannot be empty", label.getValue()); | |||
nameField.setValue("foo"); | |||
// Second validation succeeds => should be event with OK status and | |||
// no message | |||
binding.validate(); | |||
Assert.assertFalse(label.isVisible()); | |||
Assert.assertEquals("", label.getValue()); | |||
} | |||
@Test | |||
public void withStatusLabel_defaultStatusChangeHandlerIsReplaced() { | |||
Label label = new Label(); | |||
@@ -507,6 +553,26 @@ public class BinderTest { | |||
Assert.assertNull(nameField.getComponentError()); | |||
} | |||
@Test | |||
public void bindingWithStatusLabel_defaultStatusChangeHandlerIsReplaced() { | |||
Label label = new Label(); | |||
Binding<Person, String, String> binding = binder.forField(nameField) | |||
.withValidator(notEmpty).withStatusLabel(label); | |||
binding.bind(Person::getFirstName, Person::setLastName); | |||
Assert.assertNull(nameField.getComponentError()); | |||
nameField.setValue(""); | |||
// First validation fails => should be event with ERROR status and | |||
// message | |||
binding.validate(); | |||
// default behavior should update component error for the nameField | |||
Assert.assertNull(nameField.getComponentError()); | |||
} | |||
@Test(expected = IllegalStateException.class) | |||
public void withStatusChangeHandler_addAfterBound() { | |||
Binding<Person, String, String> binding = binder.forField(nameField) |