diff options
author | Pekka Hyvönen <pekka@vaadin.com> | 2017-03-20 17:05:29 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-20 17:05:29 +0200 |
commit | 2618b8e2cc592a773396a16fd7dccc8b1a0fcd9d (patch) | |
tree | 9c10515a80da3af26ef8142d544959f930eadbd6 /documentation/datamodel/datamodel-hierarchical.asciidoc | |
parent | 69b43cb346b504d713e458b987e65f4db1b825df (diff) | |
download | vaadin-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.asciidoc | 130 |
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. |