diff options
author | Denis Anisimov <denis@vaadin.com> | 2016-08-18 09:46:14 +0300 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2016-08-18 08:09:43 +0000 |
commit | 78c6ab1852f18b142390b8852e5c10e1f017dd8f (patch) | |
tree | 1fb7bad65d1ded3e7b2095630a412294d4b446fe | |
parent | 97e4ef4aa5bd56ca46ac477c1be33d44411aca17 (diff) | |
download | vaadin-framework-78c6ab1852f18b142390b8852e5c10e1f017dd8f.tar.gz vaadin-framework-78c6ab1852f18b142390b8852e5c10e1f017dd8f.zip |
Binding.validate() should fire a validation status event (#134).
Change-Id: I2121ec8f90ffcdf2fdfa02bf99084b539b27180e
3 files changed, 119 insertions, 3 deletions
diff --git a/server/src/main/java/com/vaadin/data/Binder.java b/server/src/main/java/com/vaadin/data/Binder.java index 4230bd379a..d4501955d6 100644 --- a/server/src/main/java/com/vaadin/data/Binder.java +++ b/server/src/main/java/com/vaadin/data/Binder.java @@ -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))); } diff --git a/server/src/test/java/com/vaadin/data/BinderBookOfVaadinTest.java b/server/src/test/java/com/vaadin/data/BinderBookOfVaadinTest.java index 053f4756c4..a50e06d10f 100644 --- a/server/src/test/java/com/vaadin/data/BinderBookOfVaadinTest.java +++ b/server/src/test/java/com/vaadin/data/BinderBookOfVaadinTest.java @@ -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"); @@ -311,6 +311,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(); diff --git a/server/src/test/java/com/vaadin/data/BinderTest.java b/server/src/test/java/com/vaadin/data/BinderTest.java index a4f8f83425..fddae9ac99 100644 --- a/server/src/test/java/com/vaadin/data/BinderTest.java +++ b/server/src/test/java/com/vaadin/data/BinderTest.java @@ -461,6 +461,25 @@ public class BinderTest { } @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(); @@ -488,6 +507,33 @@ public class BinderTest { } @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) |