Skip to content

Commit e9f6e48

Browse files
committed
reorganize data binding page
1 parent 4ee6459 commit e9f6e48

File tree

3 files changed

+66
-54
lines changed

3 files changed

+66
-54
lines changed

articles/components/grid/data-binding.adoc

Lines changed: 16 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ section-nav: badge-flow
99
= Binding Data to Grid [badge-flow]#Flow#
1010
:toclevels: 2
1111

12-
Grid supports connecting to various types of data sources through data providers. A data provider is a class that implements the [interfacename]`DataProvider` interface and encapsulates the logic for fetching items from a specific data source, with support for pagination, sorting, and filtering. Grid provides convenience methods to simplify common binding cases where a full data provider setup isn't needed, and also supports fully custom data providers for more complex scenarios.
12+
Grid supports connecting to various types of data sources through data providers. A data provider is a class that implements the `DataProvider` interface and encapsulates the logic for fetching items from a specific data source, with support for pagination, sorting, and filtering. For common use cases, Grid provides convenience methods so that you don't have to deal with the full data provider setup, and it also supports custom data providers where more flexibility is needed.
1313

1414
== Binding Items via `setItems`
1515

16-
The simplest way to bind data to a Grid is by using the `setItems` convenience method. It lets you bind an in-memory collection or provide callbacks for lazy loading from a backend service without explicitly creating a data provider.
16+
The most straightforward way to bind data to a Grid is to use the `setItems` convenience method. It allows you to bind an in-memory collection or provide callbacks for lazy loading from a backend service without the need to explicitly create a data provider.
1717

18-
*Example:* Binding items from an in-memory collection.
18+
The example below shows how to display, filter and sort a static list of `Person` records:
1919

2020
[.example]
2121
--
@@ -71,7 +71,7 @@ public record Person(String name) {
7171

7272
--
7373

74-
*Example:* Binding items from a data service via callbacks.
74+
The next example shows how to display, filter and sort data from a backend service with lazy loading by providing fetch and count callbacks to the `setItems` method:
7575

7676
[.example]
7777
--
@@ -165,66 +165,29 @@ More documentation and examples for using the `setItems` method are available in
165165

166166
== Custom Data Providers
167167

168-
Alternatively, you can supply a custom data provider via the `setDataProvider(DataProvider<T, ?>)` method, passing your own class that implements the [interfacename]`DataProvider` interface:
168+
A more advanced way to bind data to a Grid is to supply a custom data provider implementation via the `setDataProvider(DataProvider<T, F>)` method.
169169

170-
[source,java]
171-
----
172-
grid.setDataProvider(new CustomDataProvider());
173-
----
174-
175-
For convenience, Flow provides an abstract base class `AbstractDataProvider`, which you can extend to create a custom data provider. This class requires implementing the following methods:
176-
177-
[source,java]
178-
----
179-
public class CustomDataProvider extends AbstractDataProvider<T, F> {
180-
@Override
181-
public boolean isInMemory() { // <1>
182-
// Your implementation here
183-
}
184-
185-
@Override
186-
public int size(Query<T, F> query) { // <2>
187-
// Your implementation here
188-
}
189-
190-
@Override
191-
public Stream<T> fetch(Query<T, F> query) { // <3>
192-
// Your implementation here
193-
}
194-
}
195-
----
196-
<1> The [methodname]`isInMemory` method indicates whether the data provider uses an in-memory data source. When all data is held in memory, Grid can enable features like a determinate Select All checkbox, which is only available in this case.
197-
<2> The [methodname]`size` method returns the number of items based on the query parameters.
198-
<3> The [methodname]`fetch` method returns a stream of items based on the query parameters.
199-
200-
The `Query<T, F>` parameter in the `size` and `fetch` methods provides information about the requested data such as pagination details (offset and limit), sorting orders, and an optional filter object of type `F`.
201-
202-
Below is a practical example of a custom data provider that extends the `AbstractDataProvider` class and uses a fake database to return `Person` records. It supports filtering with a `PersonFilter` object and sorting using `QuerySortOrder` objects from the Grid. The example also includes a simple view that uses the data provider with a Grid and filter components:
170+
The example below shows a Grid backed by a custom data provider that simulates fetching data from a database, with support for filtering and sorting:
203171

204172
[.example]
205173
--
206174

207175
[source,java]
208176
.PersonDataProvider.java
209177
----
210-
public class PersonDataProvider extends AbstractDataProvider<Person, PersonFilter> {
178+
public class PersonDataProvider extends AbstractBackendDataProvider<Person, PersonFilter> {
211179
// In a real application, data would come from a real database or backend service.
212180
// This example uses a static list for demonstration purposes only.
213-
private final List<Person> FAKE_DATABASE = Arrays.asList(
181+
private final List<Person> DATABASE = Arrays.asList(
214182
new Person("Michael Chen", "Engineering"),
215183
new Person("Sarah Johnson", "Engineering"),
216184
new Person("David Rodriguez", "Marketing"),
217-
new Person("Emma Wilson", "HR"),
218-
219-
@Override
220-
public boolean isInMemory() {
221-
return false;
222-
}
185+
new Person("Emma Wilson", "HR"));
223186
224187
@Override
225-
public Stream<Person> fetch(Query<Person, PersonFilter> query) {
188+
protected Stream<Person> fetchFromBackEnd(Query<Person, PersonFilter> query) {
226189
// SQL equivalent: SELECT ... FROM ...
227-
Stream<Person> stream = FAKE_DATABASE.stream();
190+
Stream<Person> stream = DATABASE.stream();
228191
229192
// SQL equivalent: WHERE ...
230193
stream = stream.filter(createPredicate(query.getFilter()));
@@ -239,9 +202,9 @@ public class PersonDataProvider extends AbstractDataProvider<Person, PersonFilte
239202
}
240203
241204
@Override
242-
public int size(Query<Person, PersonFilter> query) {
205+
protected int sizeInBackEnd(Query<Person, PersonFilter> query) {
243206
// SQL equivalent: SELECT COUNT(*) FROM ...
244-
Stream<Person> stream = FAKE_DATABASE.stream();
207+
Stream<Person> stream = DATABASE.stream();
245208
246209
// SQL equivalent: WHERE ...
247210
stream = stream.filter(createPredicate(query.getFilter()));
@@ -346,3 +309,6 @@ public class PeopleView extends VerticalLayout {
346309
----
347310

348311
--
312+
313+
More examples of custom data providers are available in the <<{articles}/flow/binding-data/data-provider#recycling-data-binding-logic,Binding Items To Components>> article.
314+

articles/components/grid/index.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ endif::[]
325325

326326
--
327327

328-
See the <<../grid/data-binding#custom-data-providers,Data Binding>> page for more information about creating data providers for Grid.
328+
See the <<../grid/data-binding#custom-data-providers,Data Binding>> page for more information about data providers.
329329

330330
=== Lazy Column Rendering
331331

articles/flow/binding-data/data-provider.adoc

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -580,15 +580,15 @@ public static void listItems(Grid<Person> grid, PersonRepository repository) {
580580
}
581581
----
582582

583-
You can create a separate data provider class. The following example uses only the [classname]`FetchCallBack`, but you can also implement a full data provider by extending [classname]`AbstractbackendDataProvider`.
583+
To completely split off the lazy data binding logic from UI components, you can create a separate data provider class. The following example shows a data provider with only a fetch callback:
584584

585585
[source,java]
586586
----
587587
@SpringComponent
588588
public class PersonDataProvider implements CallbackDataProvider.FetchCallback<Person, Void> {
589589
590590
@Autowired
591-
PersonRepository repo;
591+
private PersonRepository repo;
592592
593593
@Override
594594
public Stream<Person> fetch(Query<Person, Void> query) {
@@ -598,7 +598,53 @@ public class PersonDataProvider implements CallbackDataProvider.FetchCallback<Pe
598598
599599
}
600600
601-
personGrid.setItems(dataProvider);
601+
personGrid.setDataProvider(dataProvider);
602+
----
603+
604+
You can also implement a full data provider by extending the [classname]`AbstractBackendDataProvider` class like so:
605+
606+
[source,java]
607+
----
608+
public class PersonDataProvider extends AbstractBackendDataProvider<Person, String> {
609+
@Autowired
610+
private PersonRepository repo;
611+
612+
@Override
613+
protected int sizeInBackEnd(Query<Person, String> query) {
614+
String lastNameFilter = query.getFilter().orElse("");
615+
616+
return (int) repo.countByLastnameContaining(lastNameFilter);
617+
}
618+
619+
@Override
620+
protected Stream<Person> fetchFromBackEnd(Query<Person, String> query) {
621+
String lastNameFilter = query.getFilter().orElse("");
622+
623+
return repo.findByLastnameContaining(lastNameFilter,
624+
VaadinSpringDataHelpers.toSpringPageRequest(query),
625+
VaadinSpringDataHelpers.toSpringDataSort(query)).stream();
626+
}
627+
}
628+
----
629+
630+
To use filtering with the data provider above, you need to instantiate it with a configurable filter type. This provides access to the [methodname]`setFilter()` method, which you can use to apply a filter value, as shown below:
631+
632+
[source,java]
633+
----
634+
// Create a data provider
635+
PersonDataProvider dataProvider = new PersonDataProvider();
636+
637+
// Wrap the original data provider to support configurable filtering
638+
ConfigurableFilterDataProvider<Person, Void, String>
639+
configurableFilterDataProvider = dataProvider.withConfigurableFilter();
640+
641+
// Set the wrapped data provider to the grid
642+
personGrid.setDataProvider(configurableFilterDataProvider);
643+
644+
filterTextField.addValueChangeListener(e -> {
645+
// Update the filter in the wrapped data provider on filter change
646+
configurableFilterDataProvider.setFilter(e.getValue()));
647+
});
602648
----
603649

604650

0 commit comments

Comments
 (0)