Examples
The examples below demonstrate the key features of shiny-treeview, a TreeView UI component for Shiny for Python backed by Material UI.
Each example is written using the concise Shiny Express API. The more powerful Shiny Core API is also supported. The examples run in your web browser using Shinylive, which means you can quickly test ideas by editing the source code and re-running the app.
Basic usage
Start with a simple hierarchical tree structure. Click on any item to select it.
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
#| layout: horizontal
#| viewerHeight: 300
## file: app.py
from shiny.express import input, render
from shiny_treeview import input_treeview
from data1 import tree_data
input_treeview("my_tree", tree_data)
@render.text
def value():
return f"Selected: {input.my_tree()}"
## file: data1.py
from shiny_treeview import TreeItem
tree_data = [
TreeItem(
"docs",
"๐ Documents",
children=[
TreeItem("report", "๐ Report.pdf"),
TreeItem("slides", "๐ Slides.pptx"),
],
),
TreeItem("readme", "โน๏ธ README.md"),
]
## file: requirements.txt
shiny
shiny-treeview
Selection modes
With multiple selection enabled, hold Ctrl/Cmd or Shift while clicking to select multiple items. Try toggling multiple selection below by editing the multiple argument, to see how it impacts user interactions.
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
#| layout: horizontal
#| viewerHeight: 500
## file: app.py
from shiny.express import input, render
from shiny_treeview import input_treeview
from data2 import tree_data
input_treeview(
"my_tree",
tree_data,
multiple=True,
)
@render.text
def multi_value():
selected = input.my_tree()
if isinstance(selected, tuple):
return f"Selected: {', '.join(selected)}"
else:
return f"Selected: {selected}"
## file: data2.py
from shiny_treeview import TreeItem
tree_data = [
TreeItem(
id="movies",
label="๐ฌ Movies",
children=[
TreeItem(
id="action",
label="๐ฅ Action",
children=[
TreeItem(id="diehard", label="Die Hard"),
TreeItem(id="madmax", label="Mad Max: Fury Road"),
],
),
TreeItem(
id="comedy",
label="๐ Comedy",
children=[
TreeItem(id="groundhog", label="Groundhog Day"),
TreeItem(id="princess", label="The Princess Bride"),
],
),
],
),
TreeItem(
id="music",
label="๐ต Music",
children=[
TreeItem(
id="rock",
label="๐ธ Rock",
children=[
TreeItem(id="queen", label="Queen - Bohemian Rhapsody"),
TreeItem(id="beatles", label="The Beatles - Hey Jude"),
],
),
TreeItem(
id="jazz",
label="๐บ Jazz",
children=[
TreeItem(id="miles", label="Miles Davis - Kind of Blue"),
TreeItem(id="coltrane", label="John Coltrane - A Love Supreme"),
],
),
],
),
TreeItem(
id="podcasts",
label="๐๏ธ Podcasts",
children=[
TreeItem(id="tech-podcast", label="Tech Talk Weekly"),
],
),
TreeItem(id="home-video", label="๐น Family Vacation 2023"),
]
## file: requirements.txt
shiny
shiny-treeview
Checkbox selection
When checkboxes are enabled, a tree item is selected by clicking on the checkbox element. This decouples the select action from the expand/contract action. Now multiple tree items can be selected without holding down a key.
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
#| layout: horizontal
#| viewerHeight: 500
## file: app.py
from shiny.express import input, render
from shiny_treeview import input_treeview
from data3 import tree_data
input_treeview(
"my_tree",
tree_data,
multiple=True,
checkbox=True,
)
@render.text
def value():
return f"Selected: {input.my_tree()}"
## file: data3.py
from shiny_treeview import TreeItem
tree_data = [
TreeItem(
id="groceries",
label="๐ Groceries",
children=[
TreeItem(
id="produce",
label="๐ฅฌ Produce",
children=[
TreeItem(id="bananas", label="๐ Bananas"),
TreeItem(id="spinach", label="๐ Fresh Spinach"),
TreeItem(id="tomatoes", label="๐
Cherry Tomatoes"),
],
),
TreeItem(
id="dairy",
label="๐ฅ Dairy",
children=[
TreeItem(id="milk", label="๐ฅ Whole Milk"),
TreeItem(id="cheese", label="๐ง Cheddar Cheese"),
TreeItem(id="yogurt", label="๐ฅ Greek Yogurt"),
],
),
],
),
TreeItem(
id="household",
label="๐ Household",
children=[
TreeItem(
id="cleaning",
label="๐งฝ Cleaning",
children=[
TreeItem(id="detergent", label="๐งด Laundry Detergent"),
TreeItem(id="sponges", label="๐งฝ Kitchen Sponges"),
],
),
],
),
TreeItem(id="batteries", label="๐ AA Batteries"),
TreeItem(id="gift", label="๐ Birthday Gift Wrap"),
]
## file: requirements.txt
shiny
shiny-treeview
Working with flat data
Transform flat data (like CSV or database results) into hierarchical trees using the stratify helper functions. If the hierarchy structure is expressed through a parent ID field, then use stratify_by_parent().
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
#| layout: horizontal
#| viewerHeight: 500
## file: app.py
from shiny.express import input, render
from shiny_treeview import input_treeview, stratify_by_parent, TreeItem
from data4 import read_data
employees_db = read_data()
employees, manager_ids = [], []
for row in employees_db.values():
label = "{icon} {name} ({title})".format(**row)
employees.append(TreeItem(id=row["employee_id"], label=label))
manager_ids.append(row["manager_id"] if row["manager_id"] else None)
# Convert flat data into hierarchical tree
tree_data = stratify_by_parent(employees, manager_ids)
input_treeview("org_tree", tree_data, selected="7")
@render.text
def selected_employee():
selected = input.org_tree()
if not selected:
return "No employee selected"
return employees_db[selected]["name"]
## file: data4.py
import csv
from io import StringIO
# Sample CSV data representing an organizational chart
# In practice, this could be loaded from a file or database
csv_data = """employee_id,name,title,manager_id
1,Sarah Chen,CEO,
2,Alex Rodriguez,CTO,1
3,Maya Patel,CFO,1
4,Jordan Kim,Senior Engineer,2
5,Riley Thompson,Engineer,2
6,Casey Davis,UX Designer,2
7,Sam Wilson,Analyst,3
8,Taylor Brown,Accountant,3"""
role_icons = {
"CEO": "๐",
"CTO": "๐ป",
"CFO": "๐ฐ",
"Senior Engineer": "๐ง",
"Engineer": "๐ง",
"UX Designer": "๐จ",
"Analyst": "๐",
"Accountant": "๐",
}
def read_data() -> dict[str, dict]:
"""Parse CSV data and return list of employee records with icons."""
reader = csv.DictReader(StringIO(csv_data))
rows = {}
for row in reader:
row["icon"] = role_icons.get(row["title"], "๐ค")
rows[row["employee_id"]] = row
return rows
## file: requirements.txt
shiny
shiny-treeview