I aim to apply a filter to the datatable using the tree input, which incorporates a hierarchical code with four levels. I intend for the datatable to consistently filter based on the fourth-level code whenever any parent level is selected. How can I implement this using the tree input?
Below is my script.
library(shiny)
library(jsTreeR)
ui <- fluidPage(
dropdownButton(
inputId = "mydropdown",
label = "Select products",
icon = "",
status = "primary",
circle = FALSE,
jstreeOutput("mytree")
),
DTOutput("table")
)
server <- function(input, output, session) {
df <- data.frame(
all = c("All product","All product","All product","All product","All product","All product","All product","All product",
"All product","All product","All product","All product","All product","All product","All product","All product"),
category = c("Agriculture","Agriculture","Agriculture","Agriculture", "Agriculture","Agriculture","Agriculture","Agriculture",
"Non Agriculture", "Non Agriculture", "Non Agriculture", "Non Agriculture","Non Agriculture", "Non Agriculture", "Non Agriculture", "Non Agriculture"),
HS2 = c("01","01","01","01","02","02","02","02","03","03","03","03","04","04","04","04"),
HS4 = c("0101","0101","0102","0102","0201","0201","0202","0202","0301","0301","0302","0302","0401","0401","0402","0402"),
HS6 = c("010101","010102", "010201","010202","020101","020102","020201","020202","030101","030102", "030201","030202","040101","040102","040201","040202")
)
output$mytree <- renderJstree({
makeNodes <- function(leaves){
dfs <- lapply(strsplit(leaves, "/"), function(s){
item <-
Reduce(function(a,b) paste0(a,"/",b), s[-1], s[1], accumulate = TRUE)
data.frame(
item = item,
parent = c("root", item[-length(item)]),
stringsAsFactors = FALSE
)
})
dat <- dfs[[1]]
for(i in 2:length(dfs)){
dat <- merge(dat, dfs[[i]], all = TRUE)
}
f <- function(parent){
i <- match(parent, dat$item)
item <- dat$item[i]
children <- dat$item[dat$parent==item]
label <- tail(strsplit(item, "/")[[1]], 1)
if(length(children)){
list(
text = label,
children = lapply(children, f),
icon =FALSE,
state = list(selected = TRUE, opened = FALSE )
)
}else{
list(text = label, type = "child",icon = FALSE,
state = list(selected = TRUE,opened = FALSE ))
}
}
lapply(dat$item[dat$parent == "root"], f)
}
# the dataframe
# transform it to a vector of paths
paths <- apply(df, 1, function(x) paste0(x, collapse = "/"))
# make the nodes list
nodes <- makeNodes(paths)
jstree(
nodes,
checkboxes = TRUE,
theme = "proton",
checkCallback = JS("$.jstree.defaults.core.expand_selected_onload = false;")
)
})
output$table <- renderDT({
datatable(df)
})
}
shinyApp(ui, server)
The paths whose ending node is checked are in
input$mytree_checked_paths
, so you can use this input to filter the dataframe.