Loading From and Saving To Business Objects
Once your bindings are set up, you are ready to fill the bound UI components with data from your business objects.
Changes can be written to business objects automatically or manually.
Reading and Writing Automatically
Writing to business objects automatically when the user makes changes in the UI is ususally 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 writing to only update the object 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 attempt to save the values to a business object, even if the user has not edited a field.
Example: Explicitly validating a form.
// This will make 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 a number of 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 update of the values of the bound fields. -
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 returning from the method. Remember to check your getters/setters to ensure there are no unwanted side effects.
|
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 appropriately enable and disable the form buttons, 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);
});
9F8453AF-3997-4C21-9F85-51F0B9D2B6A2