diff options
author | Teemu Suo-Anttila <tsuoanttila@users.noreply.github.com> | 2017-09-19 16:09:56 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-19 16:09:56 +0300 |
commit | 1f59cb51af097b8e314fde6d7c3a25821d13868d (patch) | |
tree | d0541765efd5039adce7119b8261232ef9977a8c /server | |
parent | 159d21f55f0ef24fc2a1a31661be3227988a41ee (diff) | |
download | vaadin-framework-1f59cb51af097b8e314fde6d7c3a25821d13868d.tar.gz vaadin-framework-1f59cb51af097b8e314fde6d7c3a25821d13868d.zip |
Add API for running BindingValidationStatusHandlers (#9966)
This patch adds an API to Binding for accessing the validation status handlers from a custom BinderValidationStatusHandler.
Diffstat (limited to 'server')
4 files changed, 111 insertions, 12 deletions
diff --git a/server/src/main/java/com/vaadin/data/Binder.java b/server/src/main/java/com/vaadin/data/Binder.java index 0582182d16..75d210eb61 100644 --- a/server/src/main/java/com/vaadin/data/Binder.java +++ b/server/src/main/java/com/vaadin/data/Binder.java @@ -127,6 +127,15 @@ public class Binder<BEAN> implements Serializable { public BindingValidationStatus<TARGET> validate(); /** + * Gets the validation status handler for this Binding. + * + * @return the validation status handler for this binding + * + * @since 8.2 + */ + public BindingValidationStatusHandler getValidationStatusHandler(); + + /** * Unbinds the binding from its respective {@code Binder} * Removes any {@code ValueChangeListener} {@code Registration} from * associated {@code HasValue} @@ -134,7 +143,6 @@ public class Binder<BEAN> implements Serializable { * @since 8.2 */ public void unbind(); - } /** @@ -990,8 +998,9 @@ public class Binder<BEAN> implements Serializable { return binder; } - private void notifyStatusHandler(BindingValidationStatus<?> status) { - statusHandler.statusChange(status); + @Override + public BindingValidationStatusHandler getValidationStatusHandler() { + return statusHandler; } } @@ -1948,9 +1957,7 @@ public class Binder<BEAN> implements Serializable { protected void handleBinderValidationStatus( BinderValidationStatus<BEAN> binderStatus) { // let field events go to binding status handlers - binderStatus.getFieldValidationStatuses() - .forEach(status -> ((BindingImpl<?, ?, ?>) status.getBinding()) - .notifyStatusHandler(status)); + binderStatus.notifyBindingValidationStatusHandlers(); // show first possible error or OK status in the label if set if (getStatusLabel().isPresent()) { diff --git a/server/src/main/java/com/vaadin/data/BinderValidationStatus.java b/server/src/main/java/com/vaadin/data/BinderValidationStatus.java index 90600f1800..151a4b549b 100644 --- a/server/src/main/java/com/vaadin/data/BinderValidationStatus.java +++ b/server/src/main/java/com/vaadin/data/BinderValidationStatus.java @@ -23,6 +23,7 @@ import java.util.Objects; import java.util.stream.Collectors; import com.vaadin.data.Binder.BindingBuilder; +import com.vaadin.server.SerializablePredicate; /** * Binder validation status change. Represents the outcome of binder level @@ -33,8 +34,8 @@ import com.vaadin.data.Binder.BindingBuilder; * Note: if there are any field level validation errors, the bean level * validation is not run. * <p> - * Use {@link Binder#setValidationStatusHandler(BinderValidationStatusHandler)} to handle - * form level validation status changes. + * Use {@link Binder#setValidationStatusHandler(BinderValidationStatusHandler)} + * to handle form level validation status changes. * * @author Vaadin Ltd * @@ -188,4 +189,34 @@ public class BinderValidationStatus<BEAN> implements Serializable { return binderStatuses.stream().filter(ValidationResult::isError) .collect(Collectors.toList()); } + + /** + * Notifies all validation status handlers in bindings. + * + * @see #notifyBindingValidationStatusHandlers(SerializablePredicate) + * + * @since 8.2 + */ + public void notifyBindingValidationStatusHandlers() { + notifyBindingValidationStatusHandlers(t -> true); + } + + /** + * Notifies validation status handlers for bindings that pass given filter. + * The filter should return {@code true} for each + * {@link BindingValidationStatus} that should be delegated to the status + * handler in the binding. + * + * @see #notifyBindingValidationStatusHandlers() + * + * @param filter + * the filter to select bindings to run status handling for + * + * @since 8.2 + */ + public void notifyBindingValidationStatusHandlers( + SerializablePredicate<BindingValidationStatus<?>> filter) { + bindingStatuses.stream().filter(filter).forEach(s -> s.getBinding() + .getValidationStatusHandler().statusChange(s)); + } } diff --git a/server/src/main/java/com/vaadin/data/BinderValidationStatusHandler.java b/server/src/main/java/com/vaadin/data/BinderValidationStatusHandler.java index 9f144ac430..3bfa9c863a 100644 --- a/server/src/main/java/com/vaadin/data/BinderValidationStatusHandler.java +++ b/server/src/main/java/com/vaadin/data/BinderValidationStatusHandler.java @@ -21,8 +21,9 @@ import com.vaadin.ui.AbstractComponent; /** * Handler for {@link BinderValidationStatus} changes. * <p> - * {@link Binder#setValidationStatusHandler(BinderValidationStatusHandler) Register} an - * instance of this class to be able to customize validation status handling. + * {@link Binder#setValidationStatusHandler(BinderValidationStatusHandler) + * Register} an instance of this class to be able to customize validation status + * handling. * <p> * The default handler will show * {@link AbstractComponent#setComponentError(com.vaadin.server.ErrorMessage) an @@ -53,5 +54,4 @@ public interface BinderValidationStatusHandler<BEAN> * the changed status */ void statusChange(BinderValidationStatus<BEAN> statusChange); - } diff --git a/server/src/test/java/com/vaadin/data/BinderTest.java b/server/src/test/java/com/vaadin/data/BinderTest.java index 99317745d5..4d3fe2db9b 100644 --- a/server/src/test/java/com/vaadin/data/BinderTest.java +++ b/server/src/test/java/com/vaadin/data/BinderTest.java @@ -749,6 +749,68 @@ public class BinderTest extends BinderTestBase<Binder<Person>, Person> { String.valueOf(item.getAge()), ageField.getValue()); } + static class MyBindingHandler implements BindingValidationStatusHandler { + + boolean expectingError = false; + int callCount = 0; + + @Override + public void statusChange(BindingValidationStatus<?> statusChange) { + ++callCount; + if (expectingError) { + Assert.assertTrue("Expecting error", statusChange.isError()); + } else { + Assert.assertFalse("Unexpected error", statusChange.isError()); + } + } + } + + @Test + public void execute_binding_status_handler_from_binder_status_handler() { + MyBindingHandler bindingHandler = new MyBindingHandler(); + binder.forField(nameField) + .withValidator(t -> !t.isEmpty(), "No empty values.") + .withValidationStatusHandler(bindingHandler) + .bind(Person::getFirstName, Person::setFirstName); + + String ageError = "CONVERSIONERROR"; + binder.forField(ageField) + .withConverter(new StringToIntegerConverter(ageError)) + .bind(Person::getAge, Person::setAge); + + binder.setValidationStatusHandler(status -> { + status.notifyBindingValidationStatusHandlers(); + }); + + String initialName = item.getFirstName(); + int initialAge = item.getAge(); + + binder.setBean(item); + + // Test specific error handling. + bindingHandler.expectingError = true; + nameField.setValue(""); + + // Test default error handling. + ageField.setValue("foo"); + Assert.assertTrue("Component error does not contain error message", + ageField.getComponentError().getFormattedHtmlMessage() + .contains(ageError)); + + // Restore values and test no errors. + ageField.setValue(String.valueOf(initialAge)); + Assert.assertNull("There should be no component error", + ageField.getComponentError()); + + bindingHandler.expectingError = false; + nameField.setValue(initialName); + + // Assert that the handler was called. + Assert.assertEquals( + "Unexpected callCount to binding validation status handler", 4, + bindingHandler.callCount); + } + @Test public void removed_binding_not_updates_value() { Binding<Person, Integer> binding = binder.forField(ageField) @@ -766,6 +828,5 @@ public class BinderTest extends BinderTestBase<Binder<Person>, Person> { Assert.assertEquals("Binding still affects bean even after unbind", ageBeforeUnbind, String.valueOf(item.getAge())); - } } |