shinyTree
是一种可能性。但存在一些潜在的问题:可以将子项拖入子项,或将父项拖入子项,或将父项拖入父项。我不知道是否有办法防止这种情况(我认为没有内置的方法)。
library(shiny)
library(shinyTree)
values_parents <- function(tree){
sapply(tree, function(parent) attr(parent, "stinfo"))
}
total_values_children <- function(tree){
sapply(
lapply(tree, function(parent){
sapply(parent, function(children){
attr(children, "stinfo")
})
}),
function(x){if(is.list(x)) NA else sum(x)}
)
}
ui <- fluidPage(
tags$head(
tags$style(HTML("pre {font-size: 17px;} .jstree-anchor {font-size: large;}"))
),
fluidRow(
column(
width = 6,
shinyTree("tree", dragAndDrop = TRUE, checkbox = FALSE)
),
column(
width = 6,
tags$fieldset(
tags$legend("Values of parents:"),
verbatimTextOutput("parentsValues")
),
br(),
tags$fieldset(
tags$legend("Total value of children:"),
verbatimTextOutput("childrenTotalValue")
)
)
)
)
server <- function(input, output, session) {
output[["tree"]] <- renderTree({
list(
ParentA = structure(list(
ChildrenA1 = structure(NA, stinfo = 5),
ChildrenA2 = structure(NA, stinfo = 4)
),
stinfo = 10, stopened = FALSE),
ParentB = structure(list(
ChildrenB1 = structure(NA, stinfo = 6),
ChildrenB2 = structure(NA, stinfo = 8)
),
stinfo = 12, stopened = FALSE)
)
})
output[["parentsValues"]] <- renderPrint({
values_parents(input[["tree"]])
})
output[["childrenTotalValue"]] <- renderPrint({
total_values_children(input[["tree"]])
})
}
shinyApp(ui, server)
EDIT
I started做一个新的包:jsTreeR https://github.com/stla/jsTreeR. As shinyTree
,它是 JavaScript 库的 R 接口jsTree
,但它允许更多控制。正如您在下面的示例中看到的,您不能拖动父级,也不能在子级内移动子级:
library(jsTreeR)
dat <- list(
list(
text = "RootA",
data = list(value = 999),
type = "root",
children = list(
list(
text = "ChildA1",
type = "child"
),
list(
text = "ChildA2",
type = "child"
)
)
),
list(
text = "RootB",
type = "root",
children = list(
list(
text = "ChildB1",
type = "child"
),
list(
text = "ChildB2",
type = "child"
)
)
)
)
types <- list(
root = list(
icon = "glyphicon glyphicon-ok"
),
child = list(
icon = "glyphicon glyphicon-file"
)
)
checkCallback <- JS(
"function(operation, node, parent, position, more) {",
" if(operation === 'move_node') {",
" if(parent.id === '#' || parent.type === 'child') {",
" return false;", # prevent moving a child above or below the root
" }", # and moving inside a child
" }",
" return true;", # allow everything else
"}"
)
dnd <- list(
is_draggable = JS(
"function(node) {",
" if(node[0].type !== 'child') {",
" return false;",
" }",
" return true;",
"}"
)
)
jstree(
dat,
dragAndDrop = TRUE, dnd = dnd,
types = types,
checkCallback = checkCallback
)