or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced.mdcomponents.mdcore-framework.mddata-integration.mdindex.mdlayouts.mdsecurity.mdthemes-styling.md

data-integration.mddocs/

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