This page contains examples that combine Tree Grid features to solve common use cases.
Highlighting a Subtree Flow
Custom part names can depend on the position of an item in the hierarchy. In the example below, selecting a row highlights all of its descendants with a selected-subtree part name. The part name generator checks whether the selected item is an ancestor of the rendered item. Because part names are generated only when a row is rendered, the selection listener refreshes the descendants of both the previously and the newly selected item.
In multi-select mode, selecting a parent row selects only that row by default. To also select or deselect all of its descendants, handle the selection event and update the selection with the children of the changed items. The example below fetches the descendants from the data provider. Selection changes made on the server aren’t from the client, so the listener ignores them and doesn’t process its own updates.
package com.vaadin.demo.component.treegrid;
import com.vaadin.demo.domain.DataService;
import com.vaadin.demo.domain.Person;
import com.vaadin.flow.component.grid.Grid.SelectionMode;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.treegrid.TreeGrid;
import com.vaadin.flow.data.provider.hierarchy.HierarchicalDataProvider.HierarchyFormat;
import com.vaadin.flow.data.provider.hierarchy.HierarchicalQuery;
import com.vaadin.flow.data.provider.hierarchy.TreeData;
import com.vaadin.flow.data.provider.hierarchy.TreeDataProvider;
import com.vaadin.flow.router.Route;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Route("tree-grid-recursive-selection")
public class TreeGridRecursiveSelection extends Div {
private final TreeGrid<Person> treeGrid = new TreeGrid<>();
public TreeGridRecursiveSelection() {
TreeData<Person> treeData = new TreeData<>();
treeData.addItems(DataService.getManagers(),
manager -> DataService.getPeople(manager.getId()));
treeGrid.setDataProvider(
new TreeDataProvider<>(treeData, HierarchyFormat.FLATTENED));
treeGrid.addHierarchyColumn(Person::getFullName).setHeader("Full name");
treeGrid.addColumn(Person::getEmail).setHeader("Email");
// tag::snippet[]
treeGrid.setSelectionMode(SelectionMode.MULTI);
treeGrid.asMultiSelect().addSelectionListener(event -> {
// Ignore the programmatic selection changes made below
if (!event.isFromClient()) {
return;
}
treeGrid.asMultiSelect().updateSelection(
getItemsWithDescendants(event.getAddedSelection()),
getItemsWithDescendants(event.getRemovedSelection()));
});
// end::snippet[]
add(treeGrid);
}
// tag::snippet[]
private Set<Person> getItemsWithDescendants(Collection<Person> items) {
Set<Person> result = new HashSet<>();
for (Person item : items) {
result.add(item);
if (treeGrid.getDataProvider().hasChildren(item)) {
// HierarchicalQuery takes a filter and a parent. The filter is
// null because Tree Grid has no filter of its own, and the
// parent is the item whose direct children to fetch.
List<Person> children = treeGrid.getDataProvider()
.fetchChildren(new HierarchicalQuery<>(null, item))
.toList();
result.addAll(getItemsWithDescendants(children));
}
}
return result;
}
// end::snippet[]
}
See Grid Selection for more information about selection modes.