【发布时间】:2014-02-23 06:46:44
【问题描述】:
在一个闪亮的应用程序(由 RStudio)中,在 服务器 端,我有一个反应式,它通过解析 textInput 的内容返回变量列表。然后在selectInput 和/或updateSelectInput 中使用变量列表。
我无法让它工作。有什么建议吗?
我做了两次尝试。第一种方法是将反应式outVar 直接用于selectInput。第二种方法是在updateSelectInput 中使用反应式outVar。两者都不起作用。
服务器.R
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)
})
})
ui.R
shinyUI(
basicPage(
uiOutput("inBody"),
uiOutput("inVar")
)
)
不久前,我在shiny-discuss 上发布了同样的问题,但它引起的兴趣不大,所以我再次问,抱歉,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 向我展示了当服务器尝试在 textinput 返回其参数之前应用动态函数 outVar 时出现问题。解决方法是先检查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 的方式进行操作:也许我的构造中的不平衡支架早些时候阻止了我进行检查? 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 的努力、耐心和指导。
【问题讨论】:
-
renderUI用于动态变化的输入元素。在您的情况下,textInput最好放在 UI 中,因为不涉及动态元素。 -
@ Ramnath,这是一个精简的例子:我的设置中确实有动态元素 :-)
-
在我的问题的第一行,我写在 server 端。如果您阅读我的代码,您会发现它涵盖了所有常见情况。奇怪的是,需要在
server一侧而不是在ui一侧使用as.character包装输入。你会认为这是一个错误吗?或者这是您所期望的功能?哦!有人投了反对票,哦,好吧...... -
这不是错误。如果在调用
all.vars之前先检查input$inBody是否存在,它仍然有效。所以真正重要的不是as.character。这是gist 我的意思。
标签: r shiny shiny-reactivity