在服务器端的一个 Shiny 的应用程序中(通过RStudio),我有一个反应式,可以通过解析textInput
的内容来返回变量列表。然后在selectInput
和/或updateSelectInput
中使用变量列表。
我不能使它工作。有什么建议么?
我做了两次尝试。第一种方法是直接将反应性outVar
使用到selectInput
中。第二种方法是在outVar
中使用反应性updateSelectInput
。都不行。
服务器
shinyServer(
function(input, output, session) {
outVar <- reactive({
vars <- all.vars(parse(text=input$inBody))
vars <- as.list(vars)
return(vars)
})
output$inBody <- renderUI({
textInput(inputId = "inBody", label = h4("Enter a function:"), value = "a+b+c")
})
output$inVar <- renderUI({ ## works but the choices are non-reactive
selectInput(inputId = "inVar", label = h4("Select variables:"), choices = list("a","b"))
})
observe({ ## doesn't work
choices <- outVar()
updateSelectInput(session = session, inputId = "inVar", choices = choices)
})
})
用户界面
shinyUI(
basicPage(
uiOutput("inBody"),
uiOutput("inVar")
)
)
不久前,我在 Shiny 的讨论中发布了相同的问题,但它引起的兴趣不大,所以我再次道歉,用https://groups.google.com/forum/#!topic/shiny-discuss/e0MgmMskfWo道歉
编辑1
@Ramnath友好地发布了一个似乎有效的解决方案,他表示为Edit 2。但是该解决方案无法解决问题,因为
textinput
在ui
一侧而不是在我的问题中在server
一侧。如果我将Ramnath的第二次编辑的textinput
移到server
一侧,问题再次出现,即:什么都没有显示,并且RStudio崩溃。我发现将input$text
包裹在as.character
中会使问题消失。编辑2
在进一步的讨论中,Ramnath向我展示了当服务器在
outVar
返回其参数之前尝试应用动态函数textinput
时出现了问题。解决方法是首先检查is.null(input$inBody)
是否存在。检查参数是否存在是构建 Shiny 的应用程序的关键方面,那么为什么我没有想到呢?好吧,我做到了,但是我一定做错了!考虑到我在此问题上花费的时间,这是一次痛苦的经历。我在代码之后显示如何检查是否存在。
下面是Ramnath的代码,其中
textinput
已移至server
一侧。它使RStudio崩溃,因此请勿在家中尝试。 (我用他的符号)library(shiny)
runApp(list(
ui = bootstrapPage(
uiOutput('textbox'), ## moving Ramnath's textinput to the server side
uiOutput('variables')
),
server = function(input, output){
outVar <- reactive({
vars <- all.vars(parse(text = input$text)) ## existence check needed here to prevent a crash
vars <- as.list(vars)
return(vars)
})
output$textbox = renderUI({
textInput("text", "Enter Formula", "a=b+c")
})
output$variables = renderUI({
selectInput('variables2', 'Variables', outVar())
})
}
))
我通常检查存在性的方式是这样的:
if (is.null(input$text) || is.na(input$text)){
return()
} else {
vars <- all.vars(parse(text = input$text))
return(vars)
}
Ramnath的代码更短:
if (!is.null(mytext)){
mytext = input$text
vars <- all.vars(parse(text = mytext))
return(vars)
}
两者似乎都可以工作,但是从现在起我将按照Ramnath的方式进行操作:也许结构中的不平衡支架早些时候使我无法进行检查工作? Ramnath的支票更为直接。
最后,我想谈一谈有关各种调试尝试的几件事。
在我的调试任务中,我发现有一个选项可以在服务器端对“输出”的优先级进行“排序”,这是我尝试解决问题的方法,但由于该问题在其他地方而没有用。尽管如此,很有趣的是,现在似乎还不是很知名:
outputOptions(output, "textbox", priority = 1)
outputOptions(output, "variables", priority = 2)
在该任务中,我还尝试了
try
:try(vars <- all.vars(parse(text = input$text)))
那已经很接近了,但是仍然没有解决。
我偶然发现的第一个解决方案是:
vars <- all.vars(parse(text = as.character(input$text)))
我想知道它为什么起作用会很有趣:是因为它使事情变慢了吗?是因为
as.character
“等待” input$text
不为空?无论情况如何,我都非常感谢拉姆纳特的努力,耐心和指导。
最佳答案
您需要在服务器端使用renderUI
来实现动态UI。这是一个最小的示例。请注意,第二个下拉菜单是反应性的,可调整为您在第一个菜单中选择的数据集。如果您以前处理过 Shiny 代码,则代码应该是不言自明的。
runApp(list(
ui = bootstrapPage(
selectInput('dataset', 'Choose Dataset', c('mtcars', 'iris')),
uiOutput('columns')
),
server = function(input, output){
output$columns = renderUI({
mydata = get(input$dataset)
selectInput('columns2', 'Columns', names(mydata))
})
}
))
编辑。另一种使用
updateSelectInput
的解决方案runApp(list(
ui = bootstrapPage(
selectInput('dataset', 'Choose Dataset', c('mtcars', 'iris')),
selectInput('columns', 'Columns', "")
),
server = function(input, output, session){
outVar = reactive({
mydata = get(input$dataset)
names(mydata)
})
observe({
updateSelectInput(session, "columns",
choices = outVar()
)})
}
))
EDIT2:使用
parse
的修改示例。在此应用程序中,输入的文本公式用于使用变量列表动态填充下面的下拉菜单。library(shiny)
runApp(list(
ui = bootstrapPage(
textInput("text", "Enter Formula", "a=b+c"),
uiOutput('variables')
),
server = function(input, output){
outVar <- reactive({
vars <- all.vars(parse(text = input$text))
vars <- as.list(vars)
return(vars)
})
output$variables = renderUI({
selectInput('variables2', 'Variables', outVar())
})
}
))