summaryrefslogtreecommitdiffstats
path: root/documentation/datamodel/datamodel-hierarchical.asciidoc
diff options
context:
space:
mode:
authorPekka Hyvönen <pekka@vaadin.com>2017-03-20 17:05:29 +0200
committerGitHub <noreply@github.com>2017-03-20 17:05:29 +0200
commit2618b8e2cc592a773396a16fd7dccc8b1a0fcd9d (patch)
tree9c10515a80da3af26ef8142d544959f930eadbd6 /documentation/datamodel/datamodel-hierarchical.asciidoc
parent69b43cb346b504d713e458b987e65f4db1b825df (diff)
downloadvaadin-framework-2618b8e2cc592a773396a16fd7dccc8b1a0fcd9d.tar.gz
vaadin-framework-2618b8e2cc592a773396a16fd7dccc8b1a0fcd9d.zip
Initial Documentation for TreeGrid and Hierarchical Data (#8880)
* Initial Documentation for TreeGrid and Hierarchical Data Fixes #8615, part of #8616
Diffstat (limited to 'documentation/datamodel/datamodel-hierarchical.asciidoc')
-rw-r--r--documentation/datamodel/datamodel-hierarchical.asciidoc130
1 files changed, 130 insertions, 0 deletions
diff --git a/documentation/datamodel/datamodel-hierarchical.asciidoc b/documentation/datamodel/datamodel-hierarchical.asciidoc
new file mode 100644
index 0000000000..a67a698291
--- /dev/null
+++ b/documentation/datamodel/datamodel-hierarchical.asciidoc
@@ -0,0 +1,130 @@
+---
+title: Hierarchical Data
+order: 6
+layout: page
+---
+
+[[datamodel.hierarchical]]
+= Hierarchical Data
+
+IMPORTANT: The [interfacename]#HierarchicalDataProvider# is currently being developed and only available in the Framework 8.1 prerelease versions, starting from 8.1.0.alpha1.
+
+The [classname]#TreeGrid# component allows you to show data with hierarchical relationships between items.
+That data can be populated by on-demand from a back end by implementing the [interfacename]#HierarchicalDataProvider# interface. If you have the data available in-memory on the server,
+you use the collection style API of [classname]#HierarchyData# and then pass it to a [classname]#InMemoryHierarchicalDataProvider#. This chapter introduces the hierarchical data providers and how they work. For using them with the [classname]#TreeGrid# component you should see <<dummy/../../../framework/components/components-grid.asciidoc#components.treegrid,"its documentation">>.
+
+== In-memory Hierarchical Data
+
+When the hierarchical data is available in the server side memory, you can use it to populate the [classname]#HierarchyData# that is the source of data for an [classname]#InMemoryHierarchicalDataProvider#. It contains collection style API to construct the hierarchical structure of your data, and also verifies that the hierarchy structure is valid.
+
+The following example populates a [classname]#HierarchyData# with two levels of data:
+
+[source, java]
+----
+Collection<Project> projects = service.getProjects();
+
+HierarchyData<Project> data = new HierarchyData<>();
+// add root level items
+data.addItems(null, projects);
+
+// add children for the root level items
+projects.forEach(project -> data.addItems(project, project.getChildren());
+
+// construct the data provider for the hierarchical data we've built
+InMemoryHierarchicalDataProvider<Project> dataProvider = new InMemoryHierarchicalDataProvider<>(data);
+----
+
+=== Updating data
+
+When adding or removing items from the [classname]#HierarchyData#, you need to always notify the data provider that it should refresh its data. This can be done with the [methodname]#refreshAll# method in the data provider.
+
+[source, java]
+----
+HierarchyData<Project> data = dataProvider.getHierarchyData();
+data.addItem(null, newProject);
+data.addItems(newProject, newProject.getChildren());
+
+// removes the item and all of its children
+data.removeItem(oldProject);
+
+// refresh data provider and the components it is bound to
+dataProvider.refreshAll();
+----
+
+=== Sorting and Filtering
+
+For [classname]#InMemoryHierarchicalDataProvider#, both the sorting and filtering API is the same as in [classname]ListDataProvider#. Sorting and filtering are applied separately for each hierarchy level, meaning e.g. that for a node that has not passed the filter there are no children shown.
+
+[source, java]
+----
+// setting sorting or filtering automatically refreshes the data
+dataProvider.setSortComparator((projectA, projectB) ->
+ projectA.getHours().compareTo(projectB.getHours()));
+
+dataProvider.setFilter(project -> project.getHours() > 100);
+----
+
+== Lazy Loading Hierarchical Data from a Back End
+
+The lazy loading hierarchical data, same concepts apply as with the non-hierarchical data, so you should take a look at <<dummy/../../../framework/datamodel/datamodel-providers.asciidoc#datamodel.dataproviders.lazy,"Lazy Loading Data to a Listing">> if you have not already.
+
+To load hierarchical data on-demand from your back end, you should extend the [classname]#AbstractHierarchicalDataProvider# class. Then you just have to implement the following three methods:
+
+* `boolean hasChildren(T item)`
+** This tells the data provider whether the given item has children and should be expandable. Note that this method is called frequently and should not do any costly operations.
+
+* `int getChildCount(HierarchicalQuery<T, F> query)`
+** This method returns the number of children for a certain tree level, but only for that level, excluding all subtrees
+** The parent node is available in the [classname]#HierarchicalQuery# via the [methodname]#getParent# method, which returns `null` for the root level.
+** This method is only called when a node has been expanded
+
+* `Stream<T> fetchChildren(HierarchicalQuery<T, F> query)`
+** This method returns a subset of the children for a certain tree level
+** The subset starts from the index retuned by the [methodname]#getOffset# method, thus for fetching the first item for a subtree it is always 0
+** The amount of nodes to fetch is returned by the [methodname]#getLimit# method, thus the amount of nodes returned should always (!) be the same as the _limit_.
+** The parent node is available in the [classname]#HierarchicalQuery# via the [methodname]#getParent# method, which returns `null` for the root level.
+** This method is called whenever the data should be displayed in the UI
+
+Note that the [classname]#HierarchicalQuery# query object contains the relevant information regarding the sorting and filtering.
+
+The following code snippet shows a simple example on how to building a lazy hierarchical data provider based on file system structure:
+
+[source, java]
+----
+class FileSystemDataProvider
+ extends AbstractHierarchicalDataProvider<File, FilenameFilter> {
+ private final File root;
+
+ public FileSystemDataProvider(File root) {
+ this.root = root;
+ }
+
+ @Override
+ public int getChildCount(
+ HierarchicalQuery<File, FilenameFilter> query) {
+ return (int) fetchChildren(query).count();
+ }
+
+ @Override
+ public Stream<File> fetchChildren(
+ HierarchicalQuery<File, FilenameFilter> query) {
+ final File parent = query.getParentOptional().orElse(root);
+ return query.getFilter()
+ .map(filter -> Stream.of(parent.listFiles(filter)))
+ .orElse(Stream.of(parent.listFiles()))
+ .skip(query.getOffset()).limit(query.getLimit());
+ }
+
+ @Override
+ public boolean hasChildren(File item) {
+ return item.list() != null && item.list().length > 0;
+ }
+
+ @Override
+ public boolean isInMemory() {
+ return false;
+ }
+}
+----
+
+If there are any updates on the hierarchical data, such as adding or removing rows, you should call the [methodname]#refreshAll# method that is inherited by extending [classname]#AbstractHierarchicalDataProvider#. This will reset the data. If only the data for a specific item has been updated, you can call the [methodname]#refreshItem# method to only update that item.