我遇到了一些轻微的问题(可能是错误?)和Shiny的书签 - 我动态创建UI - 新文本和数字输入。通过单击ActionButton创建这些输入。保存书签URL时 - 数字和文本输入的值都在此URL中。到现在为止还挺好。但是在加载保存的URL后,我只看到第一个动态创建的UI。我必须单击动作按钮才能添加下一个数字和文本输入。这些值保存在URL中,一旦添加了这些输入,它们就会填充正确的保存值。但是如果你有20个这样的按钮并且你必须点击19次才能将它们全部放到你的屏幕上,这有点不方便。 这是一个简短的可重复的例子。
library(shiny)
ui <- function(request){
shinyUI(fluidPage(
bookmarkButton(),
sidebarLayout(
actionButton('addElement', 'Add Element', icon("plus"), class="btn-success text-white"),
mainPanel(
id ="content"
)
)
))
}
shinyServer(function(input, output) {
enableBookmarking("url")
countvar <<- 0
observeEvent(input$addElement, {
countvar <<- countvar + 1
element <- paste0("var", countvar)
insertUI(
selector = "#content",
where = "beforeEnd",
ui = tagList(
wellPanel(
style = "display:-webkit-inline-box;width:100%",
id = element,
column(3,
textInput(element, "Element name")
),
column(3,
numericInput(paste0(element, "Value"), "Element Value", NULL)
)
)
)
)
})
})
我在SO上发现了类似的问题,遗憾的是没有答案 - Shiny app bookmarking: dynamic UI input lost
答案 0 :(得分:1)
以下是根据您的应用改编的最小示例。书签后,在页面上获取动态内容没有神奇的方法(除非您以直接的方式使用renderUI - 即没有任何非输入状态)。因此,对于您的情况,您只需在onRestore()
回调中再次重复您在应用中所做的工作。执行此操作的最佳方法是重构代码,以便可以调用一个函数来在普通应用程序和onRestore()
回调内添加项目。
library(shiny)
ui <- function(request) {
fluidPage(
bookmarkButton(),
sidebarLayout(
actionButton("add", "Add Element"),
mainPanel(id = "content")
)
)
}
server <- function(input, output, session) {
addItem <- function(id, textId, numberId, textVal = "", numberVal = NULL) {
insertUI(
selector = "#content",
where = "beforeEnd",
ui = tagList(
wellPanel(style = "display:-webkit-inline-box;width:100%",
id = id,
column(3, textInput(textId, "Element name", textVal)),
column(3, numericInput(numberId, "Element value", numberVal))
)
)
)
}
observeEvent(input$add, {
id <- paste0("var", input$add)
textId <- paste0(id, "text")
numberId <- paste0(id, "number")
addItem(id, textId, numberId)
}, ignoreInit = TRUE)
onRestore(function(state) {
for (i in seq_len(input$add)) {
id <- paste0("var", i)
textId <- paste0(id, "text")
numberId <- paste0(id, "number")
addItem(id, textId, numberId, input[[textId]], input[[numberId]])
}
})
}
enableBookmarking("url")
shinyApp(ui, server)
答案 1 :(得分:0)
这是扩展芭芭拉的答案的新方法。似乎我们需要引用onRestore
函数的状态变量,以正确处理用户的输入。因此,我更改了她的代码,使其包含似乎有效的state$input$var
。希望对您有所帮助。
library(shiny)
ui <- function(request) {
fluidPage(
bookmarkButton(),
sidebarLayout(
actionButton("add", "Add Element"),
mainPanel(id = "content")
)
)
}
server <- function(input, output, session) {
addItem <- function(id, textId, numberId, textVal = "", numberVal = NULL) {
insertUI(
selector = "#content",
where = "beforeEnd",
ui = tagList(
wellPanel(style = "display:-webkit-inline-box;width:100%",
id = id,
column(3, textInput(textId, "Element name", textVal)),
column(3, numericInput(numberId, "Element value", numberVal))
)
)
)
}
observeEvent(input$add, {
id <- paste0("var", input$add)
textId <- paste0(id, "text")
numberId <- paste0(id, "number")
addItem(id, textId, numberId)
}, ignoreInit = TRUE)
onRestore(function(state) {
for (i in seq_len(input$add)) {
id <- paste0("var", i)
textId <- paste0(id, "text")
numberId <- paste0(id, "number")
addItem(id, textId, numberId, state$input[[textId]], state$input[[numberId]])
}
})
}
enableBookmarking("server")
shinyApp(ui, server)