我正在开发一个Shiny应用程序,用户可以从数据表开始,并根据前面表格的选定过滤器/摘要创建新表格 - 如下所示:
Table1 ---- (filter) > Table2
---- (filter) > Table3 ---- (filter) > Table4
---- (filter) > Table5
---- (filter) > Table6
使用R中的列表列表,我创建了一个树数据结构(在我的代码示例中称为sliceBox.tree)来跟踪每个表/节点。 每个表都将带有一组输入:一些过滤器设置和一个actionButton,可用于在该父表下创建新的子表。
我正在使用observeEvent()函数来响应每个按钮,但是当我尝试将一个节点附加到observeEvent处理程序内的树时,只会对函数内的复制树进行更改,并且原始树不受影响。有没有办法从observeEvent处理程序内部编辑原始树,或者可能采用不同的方法来执行此操作?
以下是我的代码的精简版本,以说明问题 - 我希望当前代码通过单击任何现有按钮在页面上创建子actionButtons。
server <- function(input, output) {
newNode <- function(id, parentId) {
node <- list(
parent = parentId,
children = list(),
uiObject = createButton(id, parentId)
)
return(node)
}
createButton <- function(id, parentId) {
print(paste0("Creating button ", id))
buttonID <- paste0("sliceBoxButton", id)
return(actionButton(buttonID, paste0("I am ", buttonID, ", child of ", parentId), icon("plus-circle fa-2x")))
}
rootNode <- newNode(1, 0)
sliceBox.tree <- list(rootNode) # We'll store our nodes as a 1D list, so parent and child ID's are recorded as their indices in the list
output$debug <- renderPrint({
print(paste0("Button presses: ", v$counter))
print("FULL TREE")
print(sliceBox.tree)
})
# Keep a total count of all the button presses (also used loosely as the number of tables created)
v <- reactiveValues(counter = 1L)
# Event handlers: specific function for particular button will run when that button is pressed
observeEvent(v$counter, {
for (id in 1:v$counter) {
buttonID <- paste0("sliceBoxButton", id)
observeEvent(input[[buttonID]], {
v$counter <- v$counter + 1L
print(paste0("Pressed ", buttonID))
# Append new child to list of children
numChildren <- length(sliceBox.tree[[id]]$children)
sliceBox.tree[[id]]$children[numChildren + 1] <- v$counter
sliceBox.tree[[v$counter]] <- newNode(v$counter, id)
print(paste0("Appending node to tree at index ", v$counter))
print(sliceBox.tree)
})
}
})
# renderUI needs a list of uiObjects, so we just extract the uiObjects from every node of the tree
output$allSliceBoxes <- renderUI({
table_output_list <- lapply(1:v$counter, function(i) {
return(getElement(sliceBox.tree[[i]], 'uiObject'))
})
do.call(tagList, table_output_list) # Convert the list to a tagList
})
}
ui <- fluidPage(
uiOutput("allSliceBoxes"),
verbatimTextOutput('debug')
)
shinyApp(ui = ui, server = server)
真的希望有人可以提供帮助,我一直在广泛搜索,但没有发现任何类似的例子 - 已经坚持了好几天了!
答案 0 :(得分:1)
解决此问题的一种方法是将树存储在reactiveValues结构中。
# sliceBox.tree <- list(rootNode)
# Use this instead:
sliceBox.tree <- reactiveValues(tree=list(rootNode))
从那时起,将每sliceBox.tree
更改为sliceBox.tree$tree
。
它对我有用。