Loading & Saving Business Objects
Form state is loaded from business objects, and can be saved normally after validation. Once your bindings are set up, you’re ready to fill the bound UI components with data from your business objects. Changes can be written automatically or manually to business objects.
Reading & Writing Automatically
Writing to business objects automatically when the user makes changes in the UI is usually the most convenient option.
You can bind the values directly to an instance, by allowing Binder
to automatically save values from the fields.
Example: Automatically saving field values.
Binder<Person> binder = new Binder<>();
// Field binding configuration omitted,
// it should be done here
Person person = new Person("John Doe", 1957);
// Loads the values from the person instance
// Sets person to be updated when any bound field
// is updated
binder.setBean(person);
Button saveButton = new Button("Save", event -> {
if (binder.validate().isOk()) {
// person is always up-to-date as long as
// there are no validation errors
MyBackend.updatePersonInDatabase(person);
}
});
-
The
validate()
call ensures that bean-level validators are checked when saving automatically.
Warning
|
When you use the setBean() method, the business object instance updates whenever the user changes the value of a bound field.
If another part of the application simultaneously uses the same instance, that part could display changes before the user saves.
You can prevent this by using a copy of the edited object, or by manually updating the object only when the user saves.
|
Reading Manually
You can use the readBean()
method to manually read values from a business object instance into the UI components.
Example: Using the readBean
method.
Person person = new Person("John Doe", 1957);
binder.readBean(person);
-
This example assumes that
binder
has been configured with aTextField
bound to the name property. -
The value "John Doe" displays in the field.
Validating and Writing Manually
To prevent displaying multiple errors to the user, validation errors only display after the user has edited each field and submitted (loaded) the form.
You can explicitly validate the form or try to save the values to a business object, even if the user hasn’t edited a field.
Example: Explicitly validating a form.
// This makes all current validation errors visible
BinderValidationStatus<Person> status =
binder.validate();
if (status.hasErrors()) {
notifyValidationErrors(status.getValidationErrors());
}
Writing the field values to a business object fails if any of the bound fields contain an invalid value. You can deal with invalid values in many different ways:
Example: Handling a checked exception.
try {
binder.writeBean(person);
MyBackend.updatePersonInDatabase(person);
} catch (ValidationException e) {
notifyValidationErrors(e.getValidationErrors());
}
Example: Checking a return value.
boolean saved = binder.writeBeanIfValid(person);
if (saved) {
MyBackend.updatePersonInDatabase(person);
} else {
notifyValidationErrors(binder.validate()
.getValidationErrors());
}
Example: Adding bean-level validators.
binder.withValidator(
p -> p.getYearOfMarriage() > p.getYearOfBirth(),
"Marriage year must be bigger than birth year.");
-
The
withValidator(Validator)
method runs on the bound bean after the values of the bound fields have been updated. -
Bean-level validators also run as part of
writeBean(Object)
,writeBeanIfValid(Object)
andvalidate(Object)
, if the content passes all field-level validators.
Note
|
For bean-level validators, the bean must be updated before the validator runs.
If a bean-level validator fails in writeBean(Object) or writeBeanIfValid(Object) , the bean reverts to the state it was in before it returns from the method.
Remember to check your getters/setters to ensure there are no unwanted side effects.
|
Writing as a Draft
In addition to other means of writing field values to a business object, there’s also a way to write the bean as a draft. This means that it’s not required for all field validations to pass, and bean-level validation isn’t run at all.
// This will write all values which pass conversion and field-level validation to person bean.
binder.writeBeanAsDraft(person);
// This will write all values which pass conversion to person bean, ignoring field-level validation.
binder.writeBeanAsDraft(person, true);
Tracking Binding Status
Binder
keeps track of which bindings have been updated by the user and which bindings are in an invalid state.
It fires an event when there are status changes.
You can use this event to enable and disable the form buttons appropriately, depending on the current status of the form.
Example: Enabling the Save and Reset buttons when changes are detected.
binder.addStatusChangeListener(event -> {
boolean isValid = event.getBinder().isValid();
boolean hasChanges = event.getBinder().hasChanges();
saveButton.setEnabled(hasChanges && isValid);
resetButton.setEnabled(hasChanges);
});
33EBA0BC-10B8-4DB4-922C-71AA8B0A446C