muiTreeView gives access to MUI X Tree View React components, which lets users navigate hierarchical lists of data with nested levels that can be expanded and collapsed.
Install
You can install the development version of muiTreeView like so:
remotes::install_github("lgnbhl/muiTreeView")Basic examples
MUI Rich Tree View
Use RichTreeView() with the createTree() helper function:
df <- data.frame(
pkg = c("muiTreeView", "muiTreeView", "muiTreeView"),
functions = c("SimpleTreeView", "RichTreeView", "RichTreeView"),
args = c("items", "items", "onItemSelectionToggle")
)
treeItems <- createTree(df)
RichTreeView(
items = treeItems
)
Multi selection and checkbox
You can activate checkbox selection with checkboxSelection = TRUE and multi selection with multiSelect = TRUE:
RichTreeView(
items = treeItems,
checkboxSelection = TRUE,
multiSelect = TRUE # FALSE for single select
)
Add data with createTree()
The helper function createTree() transforms your dataframe so it can be used with RichTreeView().
You can provide a vector of the column names to select and choose the level order of the tree nodes, for example:
df <- data.frame(
pkg = c("muiTreeView", "muiTreeView", "muiTreeView"),
functions = c("SimpleTreeView", "RichTreeView", "RichTreeView"),
args = c("items", "items", "onItemSelectionToggle")
)
treeItems <- createTree(df, c("functions", "pkg"))
str(treeItems, max.level = 3)
#> List of 2
#> $ :List of 3
#> ..$ label : chr "SimpleTreeView"
#> ..$ id : chr "SimpleTreeView-3435518"
#> ..$ children:List of 1
#> .. ..$ :List of 2
#> $ :List of 3
#> ..$ label : chr "RichTreeView"
#> ..$ id : chr "RichTreeView-7881784"
#> ..$ children:List of 1
#> .. ..$ :List of 2createTree() creates also unique IDs for each node by joining the name of the label with an random integer between a dash.
df <- data.frame(
pkg = c("muiTreeView", "muiTreeView", "muiTreeView"),
functions = c("SimpleTreeView", "RichTreeView", "RichTreeView"),
args = c("items", "items", "onItemSelectionToggle")
)
treeItems <- createTree(df, c("functions", "pkg"))
# treeItems <- list(
# list(
# label = "muiTreeView", id = "muiTreeView-1",
# children = list(
# list(
# label = "SimpleTreeView", id = "SimpleTreeView-2",
# children = list(
# list(label = "items", id = "items-3")
# )
# ),
# list(
# label = "RichTreeView", id = "RichTreeView-4",
# children = list(
# list(label = "items", id = "items-5"),
# list(label = "onItemClick", id = "onItemClick-6")
# )
# )
# )
# )
# )
RichTreeView(
items = treeItems
)As createTree() is adapted from shinyWidgets::create_tree(), I want to thank the authors of shinyWidgets for their amazing work!
Rich Tree View default selection and expand
Select by default one or multiple items with the defaultSelectedItems argument by providing its related IDs.
You can also expand by default one or multiple nodes with the defaultExpandedItems argument by providing its related IDs.
df <- data.frame(
pkg = c("muiTreeView", "muiTreeView", "muiTreeView"),
functions = c("SimpleTreeView", "RichTreeView", "RichTreeView"),
args = c("items", "items", "onItemSelectionToggle")
)
treeItems <- createTree(df)
defaultSelectedId <- treeItems[[1]]$children[[1]]$id
defaultExpandedId <- treeItems[[1]]$id
RichTreeView(
items = treeItems,
defaultSelectedItems = list(defaultSelectedId), # always in list()
defaultExpandedItems = list(defaultExpandedId) # always in list()
)Simple Tree View
Using SimpleTreeView() with TreeItem(), you can easily customize items with icons for example:
SimpleTreeView(
defaultExpandedItems = list("documents"), # always in list()
defaultSelectedItems = list("notes"), # always in list()
TreeItem(
itemId = "documents",
label = div(shiny::icon("folder"), " Documents"),
TreeItem(
itemId = "notes",
label = div(shiny::icon("file"), " Notes")
),
TreeItem(
itemId = "images",
label = div(shiny::icon("image"), " Images")
),
TreeItem(
itemId = "videos",
label = div(shiny::icon("video"), " Videos")
)
),
TreeItem(
itemId = "history",
label = div(shiny::icon("history"), " History")
),
TreeItem(
itemId = "trash",
label = div(shiny::icon("trash"), " Trash")
)
)
Usage with Shiny
You can get user item clicked in Shiny using the onItemSelectionToggle argument (more info here), by creating a “itemSelection” input with shiny.react::setInput().
As the “itemSelection” input returns the label name followed by a dash “-” with a random integer, you can get the cleaned label using gsub(), i.e. gsub(pattern = "\\-.*$", replacement = "", x = input$itemSelection)
Track latest item clicked
library(shiny)
df <- data.frame(
pkg = c("muiTreeView", "muiTreeView", "muiTreeView"),
functions = c("SimpleTreeView", "RichTreeView", "RichTreeView"),
args = c("items", "items", "onItemSelectionToggle")
)
treeItems <- createTree(df)
defaultExpanded <- treeItems[[1]]$id
defaultSelectedId <- treeItems[[1]]$children[[1]]$id
ui <- tagList(
reactOutput("tree"),
verbatimTextOutput("info")
)
server <- function(input, output, session) {
output$tree <- renderReact({
RichTreeView(
items = treeItems,
# expand by default a node with its id
defaultSelectedItems = list(defaultSelectedId), # always in list()
defaultExpandedItems = list(defaultExpanded), # always in list()
onItemSelectionToggle = setInput(
inputId = "itemSelection",
jsAccessor = "[1]"
)
)
})
# Reproduce logic from official MUI's documentation
selectedItems <- reactiveValues(
selected = defaultSelectedId
)
observeEvent(input$itemSelection, {
current_selection <- input$itemSelection
if(current_selection %in% selectedItems$selected) {
# Remove if already selected
new_selection <- setdiff(selectedItems$selected, current_selection)
} else {
# Add if not selected
new_selection <- c(selectedItems$selected, current_selection)
}
selectedItems$selected <- new_selection
})
output$info <- shiny::renderPrint(
# remove random ID to return only item label name
gsub(pattern = "\\-.*$", replacement = "", x = selectedItems$selected)
)
}
shinyApp(ui, server)
Track multiple items with checkbox selection
You can use reactive values to get multiple items selection by implementing the logic as showed in the official MUI documentation.
library(shiny)
df <- data.frame(
pkg = c("muiTreeView", "muiTreeView", "muiTreeView"),
functions = c("SimpleTreeView", "RichTreeView", "RichTreeView"),
args = c("items", "items", "onItemSelectionToggle")
)
treeItems <- createTree(df)
defaultExpandedId <- treeItems[[1]]$id
defaultSelectedId <- treeItems[[1]]$children[[1]]$children[[1]]$id
ui <- tagList(
reactOutput("tree"),
verbatimTextOutput("info")
)
server <- function(input, output, session) {
output$tree <- renderReact({
RichTreeView(
checkboxSelection = TRUE,
multiSelect = TRUE,
items = treeItems,
# expand by default a node with its id
defaultExpandedItems = list(defaultExpandedId), # always in list()
defaultSelectedItems = list(defaultSelectedId), # always in list()
# By default, selecting a item does not select its children.
selectionPropagation = list(
descendants = TRUE
),
onItemSelectionToggle = shiny.react::setInput(
inputId = "itemSelection",
jsAccessor = "[1]"
)
)
})
# Reproduce logic from official MUI's documentation
selectedItems <- reactiveValues(
selected = defaultSelectedId
)
observeEvent(input$itemSelection, {
current_selection <- input$itemSelection
if(current_selection %in% selectedItems$selected) {
# Remove if already selected
new_selection <- setdiff(selectedItems$selected, current_selection)
} else {
# Add if not selected
new_selection <- c(selectedItems$selected, current_selection)
}
selectedItems$selected <- new_selection
})
output$info <- shiny::renderPrint(
# remove random ID to return only item label name
gsub(pattern = "\\-.*$", replacement = "", x = selectedItems$selected)
)
}
shinyApp(ui, server)
More features
Explore the official MUI Tree View documentation to see how more features can be added.
Use other MUI products
MUI X Tree View is developed MUI, the company behind the popular React framework Material UI. muiTreeView is therefore a companion to the R package shinyMaterialUI , which provides access to all Material UI components from R.
Bootstrap conflict
muiTreeView can enter in conflict with the Bootstrap CSS framework, used by default in Shiny functions such as shiny::fluidPage() and friends.
The Bootstrap conflict could potentially be solved using Shadow DOM.
Contribute
If you have any issue, question or want to contribute with a pull request, don’t hesitate to write me on https://github.com/lgnbhl/muiTreeView
For updates follow Felix Luginbuhl on LinkedIn.