Vaadin Flow includes mechanisms to bind field components, as well as forms consisting of fields, to business objects (e.g., Java beans). Binding is buffered, so you can load and reload data from the source to fields, and then save the edited data back.
This example has a view with two editors: one writable, and one read-only. When the user clicks Save, the form data is written to the BusinessPerson object, which is reflected in the read-only form.
Source code
DataBinding.java
package com.vaadin.demo.flow.binding;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.data.binder.ValidationException;
import com.vaadin.flow.router.Route;
@Route("binding-overview")
public class DataBinding extends VerticalLayout {
public DataBinding() {
// Data model
BusinessPerson person = new BusinessPerson();
// Two editors: the actual editor and read-only display
PersonEditor editor1 = new PersonEditor(false);
PersonEditor editor2 = new PersonEditor(true);
// The editor and buttons
VerticalLayout layout1 = new VerticalLayout();
HorizontalLayout buttons = new HorizontalLayout();
Button saveButton = new Button("Save");
saveButton.addClickListener(click -> {
try {
editor1.getBinder().writeBean(person);
editor2.getBinder().readBean(person);
} catch (ValidationException e) {
}
});
Button resetButton = new Button("Reset");
resetButton.addClickListener(click -> {
editor1.getBinder().readBean(person);
});
buttons.add(saveButton, resetButton);
layout1.add(editor1, buttons);
VerticalLayout layout2 = new VerticalLayout();
layout2.add(editor2);
// Show the two editors side-by-side
HorizontalLayout hlayout = new HorizontalLayout();
hlayout.setDefaultVerticalComponentAlignment(
FlexComponent.Alignment.START);
hlayout.add(layout1, layout2);
add(hlayout);
}
}
PersonEditor.java
package com.vaadin.demo.flow.binding;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.textfield.TextField;
// tag::snippet[]
public class PersonEditor extends FormLayout {
private Binder<BusinessPerson> binder;
public PersonEditor(boolean readOnly) {
// For binding the form to the data model
binder = new Binder<>(BusinessPerson.class);
TextField nameField = new TextField();
addFormItem(nameField, "Name");
binder.bind(nameField, BusinessPerson::getName,
BusinessPerson::setName);
nameField.setReadOnly(readOnly);
TextField titleField = new TextField();
addFormItem(titleField, "Title");
binder.forField(titleField).bind(BusinessPerson::getTitle,
BusinessPerson::setTitle);
titleField.setReadOnly(readOnly);
}
public Binder<BusinessPerson> getBinder() {
return binder;
}
}
// end::snippet[]
Field and form input can be validated before saving. Additionally, when loading and saving, the data representation may need to be converted between the field type and the underlying data types in the business objects.