0
# Data Integration
1
2
Data binding and providers for connecting UI components to backend data sources.
3
4
**Quick links:** [Binder](#binder) | [DataProvider](#dataprovider) | [Hierarchical DataProvider](#hierarchical-dataprovider) | [Renderers](#renderers)
5
6
**Related components:** Grid (see [Components](../components.md#display-components)), ComboBox (see [Components](../components.md#combobox-and-select))
7
8
## Binder
9
10
Two-way data binding between UI components and Java beans.
11
12
```java { .api }
13
class Binder<BEAN> {
14
Binder();
15
Binder(Class<BEAN> beanType);
16
<FIELDVALUE> BindingBuilder<BEAN, FIELDVALUE> forField(HasValue<?, FIELDVALUE> field);
17
void setBean(BEAN bean);
18
void readBean(BEAN bean);
19
boolean writeBeanIfValid(BEAN bean) throws ValidationException;
20
BinderValidationStatus<BEAN> validate();
21
}
22
23
interface BindingBuilder<BEAN, FIELDVALUE> {
24
BindingBuilder<BEAN, FIELDVALUE> withValidator(Validator<? super FIELDVALUE> validator);
25
BindingBuilder<BEAN, FIELDVALUE> asRequired(String errorMessage);
26
<NEWTARGET> BindingBuilder<BEAN, NEWTARGET> withConverter(Converter<FIELDVALUE, NEWTARGET> converter);
27
Binding<BEAN, FIELDVALUE> bind(ValueProvider<BEAN, FIELDVALUE> getter,
28
Setter<BEAN, FIELDVALUE> setter);
29
Binding<BEAN, FIELDVALUE> bind(String propertyName);
30
}
31
32
interface Validator<T> {
33
ValidationResult apply(T value, ValueContext context);
34
}
35
```
36
37
**Examples:**
38
39
```java
40
Binder<Person> binder = new Binder<>(Person.class);
41
42
TextField firstName = new TextField("First Name");
43
binder.forField(firstName)
44
.asRequired("Required")
45
.withValidator(name -> name.length() >= 2, "Min 2 characters")
46
.bind(Person::getFirstName, Person::setFirstName);
47
48
EmailField email = new EmailField("Email");
49
binder.forField(email)
50
.asRequired("Required")
51
.bind(Person::getEmail, Person::setEmail);
52
53
// Load data
54
binder.setBean(person);
55
56
// Save data
57
if (binder.writeBeanIfValid(person)) {
58
personService.save(person);
59
Notification.show("Saved");
60
}
61
```
62
63
## DataProvider
64
65
Interface for providing data to components like Grid and ComboBox.
66
67
```java { .api }
68
interface DataProvider<T, F> {
69
Stream<T> fetch(Query<T, F> query);
70
int size(Query<T, F> query);
71
void refreshItem(T item);
72
void refreshAll();
73
static <T> ListDataProvider<T> ofCollection(Collection<T> items);
74
static <T, F> DataProvider<T, F> fromCallbacks(
75
CallbackDataProvider.FetchCallback<T, F> fetchCallback,
76
CallbackDataProvider.CountCallback<T, F> countCallback);
77
}
78
79
class ListDataProvider<T> implements DataProvider<T, SerializablePredicate<T>> {
80
ListDataProvider(Collection<T> items);
81
void setFilter(SerializablePredicate<T> filter);
82
void setSortOrder(ValueProvider<T, ?> valueProvider, SortDirection direction);
83
}
84
85
class Query<T, F> {
86
int getOffset();
87
int getLimit();
88
List<QuerySortOrder> getSortOrders();
89
Optional<F> getFilter();
90
}
91
92
abstract class AbstractBackEndDataProvider<T, F> implements DataProvider<T, F> {
93
protected abstract Stream<T> fetchFromBackEnd(Query<T, F> query);
94
protected abstract int sizeInBackEnd(Query<T, F> query);
95
}
96
```
97
98
**Examples:**
99
100
```java
101
// Grid with DataProvider
102
Grid<Customer> grid = new Grid<>(Customer.class);
103
grid.setColumns("name", "email");
104
105
DataProvider<Customer, Void> dataProvider = DataProvider.fromCallbacks(
106
query -> {
107
int offset = query.getOffset();
108
int limit = query.getLimit();
109
List<QuerySortOrder> sortOrders = query.getSortOrders();
110
return customerService.fetch(offset, limit, sortOrders).stream();
111
},
112
query -> customerService.count()
113
);
114
grid.setDataProvider(dataProvider);
115
116
// ListDataProvider with filtering
117
ListDataProvider<Product> listProvider = DataProvider.ofCollection(products);
118
TextField searchField = new TextField();
119
searchField.addValueChangeListener(e -> {
120
String term = e.getValue().toLowerCase();
121
listProvider.setFilter(p -> p.getName().toLowerCase().contains(term));
122
});
123
grid.setDataProvider(listProvider);
124
```
125
126
## Hierarchical DataProvider
127
128
For tree structures like TreeGrid.
129
130
```java { .api }
131
interface HierarchicalDataProvider<T, F> extends DataProvider<T, F> {
132
int getChildCount(HierarchicalQuery<T, F> query);
133
boolean hasChildren(T item);
134
}
135
136
abstract class AbstractBackEndHierarchicalDataProvider<T, F>
137
implements HierarchicalDataProvider<T, F> {
138
protected abstract Stream<T> fetchChildrenFromBackEnd(HierarchicalQuery<T, F> query);
139
public abstract int getChildCount(HierarchicalQuery<T, F> query);
140
public abstract boolean hasChildren(T item);
141
}
142
```
143
144
**Example:**
145
146
```java
147
TreeGrid<Department> treeGrid = new TreeGrid<>();
148
treeGrid.addHierarchyColumn(Department::getName);
149
150
HierarchicalDataProvider<Department, Void> provider =
151
new AbstractBackEndHierarchicalDataProvider<Department, Void>() {
152
@Override
153
protected Stream<Department> fetchChildrenFromBackEnd(
154
HierarchicalQuery<Department, Void> query) {
155
Department parent = query.getParent();
156
return parent == null ?
157
departmentService.fetchRoots(query.getOffset(), query.getLimit()).stream() :
158
departmentService.fetchChildren(parent, query.getOffset(), query.getLimit()).stream();
159
}
160
161
@Override
162
public int getChildCount(HierarchicalQuery<Department, Void> query) {
163
Department parent = query.getParent();
164
return parent == null ?
165
departmentService.countRoots() :
166
departmentService.countChildren(parent);
167
}
168
169
@Override
170
public boolean hasChildren(Department item) {
171
return departmentService.hasChildren(item);
172
}
173
};
174
treeGrid.setDataProvider(provider);
175
```
176
177
## Renderers
178
179
```java { .api }
180
class ComponentRenderer<C extends Component, T> implements Renderer<T> {
181
ComponentRenderer(SerializableFunction<T, C> componentProvider);
182
ComponentRenderer(SerializableFunction<T, C> componentProvider,
183
SerializableConsumer<C> componentUpdater);
184
}
185
186
class LitRenderer<T> implements Renderer<T> {
187
static <T> LitRenderer<T> of(String template);
188
LitRenderer<T> withProperty(String property, ValueProvider<T, ?> provider);
189
}
190
```
191
192
**Examples:**
193
194
```java
195
Grid<Product> grid = new Grid<>();
196
grid.addColumn(new ComponentRenderer<>(product ->
197
new HorizontalLayout(
198
new Image(product.getImageUrl(), ""),
199
new Span(product.getName())
200
)
201
));
202
203
grid.addColumn(LitRenderer.<Product>of("<b>[[item.name]]</b><br><small>[[item.description]]</small>")
204
.withProperty("name", Product::getName)
205
.withProperty("description", Product::getDescription));
206
```
207