From dda9b052604967b8d8cfec5c20d06e72f6f78d33 Mon Sep 17 00:00:00 2001 From: Tatu Lund Date: Fri, 29 Nov 2019 14:33:59 +0200 Subject: Add method writeBeanAsDraft(bean) in Binder (#11833) * Add method writeBeanAsDraft(bean) in Binder With current Binder implementation it is not easy to support Forms, which you want to save as draft, i.e. incomplete. For example there can be big text areas, that require time to fill, or lot of fields. Therefore it is needed to that form can be saved, e.g. to other bean in incomplete state when it is not yet passing validation and this other bean can be persisted to draft storage for further editing in the future. This method helps to achieve that easily. * Add test case for Binder.writeBeanAsDraft(bean) Bind a field with validator, set value that does not pass validator and save, assert that value was saved. * Updating test * Fixing logic flaw in test * Further improvement of the test case * Clarification of the JavaDoc * Fixing typo * JavaDoc language check * Fixing whitespace issue * Fixing whitespaces * Fixing whitespaces * Updating JavaDoc --- server/src/main/java/com/vaadin/data/Binder.java | 34 ++++++++++++++++++++++ .../src/test/java/com/vaadin/data/BinderTest.java | 33 +++++++++++++++++++++ 2 files changed, 67 insertions(+) (limited to 'server/src') diff --git a/server/src/main/java/com/vaadin/data/Binder.java b/server/src/main/java/com/vaadin/data/Binder.java index 699185dea3..747983bfa5 100644 --- a/server/src/main/java/com/vaadin/data/Binder.java +++ b/server/src/main/java/com/vaadin/data/Binder.java @@ -1786,6 +1786,23 @@ public class Binder implements Serializable { } } + /** + * Writes successfully converted and validated changes from the bound fields + * to the bean even if there are other fields with non-validated changes. + * + * @see #writeBean(Object) + * @see #writeBeanIfValid(Object) + * @see #readBean(Object) + * @see #setBean(Object) + * + * @param bean + * the object to which to write the field values, not + * {@code null} + */ + public void writeBeanAsDraft(BEAN bean) { + doWriteDraft(bean, new ArrayList<>(bindings)); + } + /** * Writes changes from the bound fields to the given bean if all validators * (binding and bean level) pass. @@ -1873,6 +1890,23 @@ public class Binder implements Serializable { return status; } + /** + * Writes the successfully converted and validated field values into the + * given bean. + * + * @param bean + * the bean to write field values into + * @param bindings + * the set of bindings to write to the bean + */ + @SuppressWarnings({ "unchecked" }) + private void doWriteDraft(BEAN bean, Collection> bindings) { + Objects.requireNonNull(bean, "bean cannot be null"); + + bindings.forEach(binding -> ((BindingImpl) binding) + .writeFieldValue(bean)); + } + /** * Restores the state of the bean from the given values. This method is used * together with {@link #getBeanState(Object, Collection)} to provide a way diff --git a/server/src/test/java/com/vaadin/data/BinderTest.java b/server/src/test/java/com/vaadin/data/BinderTest.java index 3e27cc5f9b..401cc07017 100644 --- a/server/src/test/java/com/vaadin/data/BinderTest.java +++ b/server/src/test/java/com/vaadin/data/BinderTest.java @@ -269,6 +269,39 @@ public class BinderTest extends BinderTestBase, Person> { assertEquals(fieldValue, person.getFirstName()); } + @Test + public void save_bound_beanAsDraft() { + Binder binder = new Binder<>(); + binder.forField(nameField) + .withValidator((value,context) -> { + if (value.equals("Mike")) return ValidationResult.ok(); + else return ValidationResult.error("value must be Mike"); + }) + .bind(Person::getFirstName, Person::setFirstName); + binder.forField(ageField) + .withConverter(new StringToIntegerConverter("")) + .bind(Person::getAge, Person::setAge); + + Person person = new Person(); + + String fieldValue = "John"; + nameField.setValue(fieldValue); + + int age = 10; + ageField.setValue("10"); + + person.setFirstName("Mark"); + + binder.writeBeanAsDraft(person); + + // name is not written to draft as validation / conversion + // does not pass + assertNotEquals(fieldValue, person.getFirstName()); + // age is written to draft even if firstname validation + // fails + assertEquals(age, person.getAge()); + } + @Test public void load_bound_fieldValueIsUpdated() { binder.bind(nameField, Person::getFirstName, Person::setFirstName); -- cgit v1.2.3