在一个闪亮的应用程序(由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")
)
)
不久前,我在发光讨论中发布了相同的问题,但它引起的兴趣不大,所以我再次问道歉,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)
是否存在。
检查是否存在参数是构建闪亮应用程序的一个重要方面 ,为什么我没有想到它?嗯,我做到了,但我一定做错了!考虑到我花在这个问题上的时间,这是一个痛苦的经历。我在代码后面显示如何检查是否存在。
下面是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的方式:我的构造中的一个不平衡的支架早些时候阻止我进行检查工作?拉姆纳特的支票更直接。
最后,我想说明一些关于我的各种调试尝试的事情。
在我的调试任务中,我发现有一个选项可以“排列”服务器端“输出”的优先级,我试图解决我的问题,但是由于问题是别处。尽管如此,知道并且目前看来并不是很有名,这很有趣:
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
为非空?
无论情况如何,我都非常感谢Ramnath的努力,耐心和指导。
答案 0 :(得分:67)
您需要在服务器端使用renderUI
来获取动态UI。这是一个最小的例子。请注意,第二个下拉菜单是被动的,并根据您在第一个选择的数据集进行调整。如果您之前处理过闪亮,代码应该是不言自明的。
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))
})
}
))
EDIT。使用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())
})
}
))
答案 1 :(得分:2)
据我所知,问题是input$inBody
无法检索character
,即使selectInput
函数的值为character
,即{ {1}}。因此,解决方案是将value = "a+b+c"
包裹在input$inBody
以下作品:
使用as.character
的{{1}}方法:
observe
使用updateSelectInput
的{{1}}方法:
observe({
input$inBody
vars <- all.vars(parse(text=as.character(input$inBody)))
vars <- as.list(vars)
updateSelectInput(session = session, inputId = "inVar", choices = vars)
})
编辑:我根据Ramnath的反馈编辑了我的问题。 Ramnath解释了这个问题并提供了一个更好的解决方案,我将其作为我的问题的编辑。我会保留这个答案,但它不值得投票。