Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions articles/components/tree-grid/recipes.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
title: Recipes
page-title: Tree Grid recipes for common use cases | Vaadin components
description: Examples that combine Tree Grid features to solve common use cases.
meta-description: Examples that combine Tree Grid features to solve common use cases.
order: 60
---

= Tree Grid Recipes

This page contains examples that combine Tree Grid features to solve common use cases.


== Highlighting a Subtree [badge-flow]#Flow#

Check failure on line 14 in articles/components/tree-grid/recipes.adoc

View workflow job for this annotation

GitHub Actions / lint

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'Subtree'? Raw Output: {"message":"[Vale.Spelling] Did you really mean 'Subtree'?","location":{"path":"articles/components/tree-grid/recipes.adoc","range":{"start":{"line":14,"column":19},"end":{"line":14,"column":26}}},"severity":"ERROR","code":{"value":"Vale.Spelling"}}

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.

[.example,themes="lumo,aura"]
--
[source,typescript]
----
include::{root}/frontend/demo/component/tree-grid/tree-grid-imports.ts[preimport,hidden]
----

[source,java]
----
include::{root}/src/main/java/com/vaadin/demo/component/treegrid/TreeGridSubtreeHighlight.java[render,tags=snippet,indent=0]
----

[source,css]
----
include::{root}/frontend/themes/docs/tree-grid-subtree-highlight.css[]
----
--

See <<../grid/styling#part-name-generator,Dynamically Styling Rows & Columns>> for more information about custom part names.
1 change: 1 addition & 0 deletions frontend/demo/component/tree-grid/tree-grid-imports.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'Frontend/demo/init';
import '@vaadin/grid';
import '@vaadin/grid/vaadin-grid-tree-toggle.js';
import '@vaadin/select';

// This file only has the required imports for the Java-only example
1 change: 1 addition & 0 deletions frontend/themes/docs/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
@import './grid-cell-focus.css';
@import './grid-styling.css';
@import './grid-header-footer-styling.css';
@import './tree-grid-subtree-highlight.css';
@import './menu-bar-class-name.css';
@import './message-list-class-name.css';
@import './multi-select-combo-box-chip-class-name.css';
Expand Down
9 changes: 9 additions & 0 deletions frontend/themes/docs/tree-grid-subtree-highlight.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* Add this to your global CSS, for example in: */
/* src/main/resources/META-INF/resources/styles.css */

vaadin-grid::part(selected-subtree) {
/* Aura */
--vaadin-grid-cell-background-color: color-mix(in srgb, currentColor 4%, transparent);
/* Lumo */
--vaadin-grid-cell-background: color-mix(in srgb, currentColor 4%, transparent);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.vaadin.demo.component.treegrid;

import com.vaadin.demo.DemoExporter; // hidden-source-line
import com.vaadin.demo.domain.DataService;
import com.vaadin.demo.domain.Person;
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.TreeData;
import com.vaadin.flow.data.provider.hierarchy.TreeDataProvider;
import com.vaadin.flow.router.Route;

@Route("tree-grid-subtree-highlight")
public class TreeGridSubtreeHighlight extends Div {

private final TreeGrid<Person> treeGrid = new TreeGrid<>();
private final TreeData<Person> treeData = new TreeData<>();

public TreeGridSubtreeHighlight() {
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::getProfession).setHeader("Profession");

// tag::snippet[]
treeGrid.setPartNameGenerator(person -> {
Person selected = treeGrid.asSingleSelect().getValue();
return isDescendantOf(person, selected) ? "selected-subtree" : null;
});

treeGrid.asSingleSelect().addValueChangeListener(event -> {
// Regenerate the part names of the previous and new subtree
refreshDescendants(event.getOldValue());
refreshDescendants(event.getValue());
});
// end::snippet[]

treeGrid.expand(DataService.getManagers().get(0));
add(treeGrid);
}

// tag::snippet[]
private boolean isDescendantOf(Person person, Person ancestor) {
if (ancestor == null) {
return false;
}
Person parent = treeData.getParent(person);
while (parent != null) {
if (parent.equals(ancestor)) {
return true;
}
parent = treeData.getParent(parent);
}
return false;
}

private void refreshDescendants(Person person) {
if (person == null) {
return;
}
for (Person child : treeData.getChildren(person)) {
treeGrid.getDataProvider().refreshItem(child);
refreshDescendants(child);
}
}
// end::snippet[]

public static class Exporter // hidden-source-line
extends DemoExporter<TreeGridSubtreeHighlight> { // hidden-source-line
} // hidden-source-line
}
Loading