Browse Source

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
tags/8.10.0.alpha1
Tatu Lund 4 years ago
parent
commit
dda9b05260
No account linked to committer's email address

+ 34
- 0
server/src/main/java/com/vaadin/data/Binder.java View File

@@ -1786,6 +1786,23 @@ public class Binder<BEAN> 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<BEAN> 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<Binding<BEAN, ?>> bindings) {
Objects.requireNonNull(bean, "bean cannot be null");

bindings.forEach(binding -> ((BindingImpl<BEAN, ?, ?>) 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

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

@@ -269,6 +269,39 @@ public class BinderTest extends BinderTestBase<Binder<Person>, Person> {
assertEquals(fieldValue, person.getFirstName());
}

@Test
public void save_bound_beanAsDraft() {
Binder<Person> 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);

Loading…
Cancel
Save