Shiny:使用do.call运行render-family函数

时间:2017-10-10 21:24:46

标签: r shiny

我想使用do.call来运行渲染系列函数,例如renderPrint()。下面的代码不起作用:

rm(list=ls())

library(shiny)

ui <- fluidPage(

  selectInput("select", label = h3("Select box"), 
              choices = list("Choice 1" = 1, "Choice 2" = 2, "Choice 3" = 3), 
              selected = 1),
  hr(),
  fluidRow(column(3, verbatimTextOutput("value")))

)

server <- function(input, output, session) {

  output$value <- do.call("renderPrint", list({ input$select }))
}

shinyApp(ui, server)

错误:

Warning: Error in .getReactiveEnvironment()$currentContext: Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)
Stack trace (innermost first):
    45: .getReactiveEnvironment()$currentContext
    44: .subset2(x, "impl")$get
    43: $.reactivevalues
[...]

如何实现这一目标?我猜这在某种程度上与环境和懒惰的评估有关,所以关闭可能是解决方案,但这只是猜测...

2 个答案:

答案 0 :(得分:0)

我找到了一种基于来自SO的this answer来实现这一目标的方法。关键部分是使用alist而不是list。来自文档:

  

alist 处理其参数,就好像它们描述了函数参数一样。因此值未评估,并且允许没有值的标记参数,而list只是忽略它们。 alist通常与formals一起使用。

rm(list=ls())

library(shiny)

ui <- fluidPage(    
  selectInput("select", label = h3("Select box"), 
              choices = list("Choice 1" = 1, "Choice 2" = 2, "Choice 3" = 3), 
              selected = 1),
  hr(),
  fluidRow(column(3, verbatimTextOutput("value")))    
)

server <- function(input, output, session) {          
  output$value <- do.call(
    renderPrint, 
    alist(input$select)
  )
}

shinyApp(ui, server)

或者,您可以使用quoted中的renderPrint参数并在表达式周围包裹quote,但我对此方法没有好运。

答案 1 :(得分:0)

注意:我试图在评论中添加格雷戈尔的答案,但有点失败。请先读一读!

do.call在构造调用时默认评估其参数。

但是你可以指定quote = TRUE让args无法评估:

output$value <- do.call(renderPrint, list(quote(input$select), quoted = TRUE), quote = TRUE)

但更简单的方法是在调用中使用带引号的arg:

output$value <- do.call(renderPrint, list(quote(input$select)))

然后在调用时评估引用的表达式,并且您不会在被动上下文之外评估input$select