Shiny:动态UI - 围绕downloadHandler的循环?

时间:2014-09-23 15:13:19

标签: r shiny

我有一个简单的示例Siny代码可以正常工作(下面)。它生成一个包含几个微小数据帧的列表(server.R中的反应对象'myout')。数据帧的数量基于用户的输入。('NumRuns')。 我当前的代码允许用户下载第一个数据帧 - 通过ui.R中的downloadButton和server.r中的downloadHandler。 我想知道是否有可能围绕downloadButton和downloadHandler创建一个循环,以便 - 在运行分析(actionButton)之后 - 用户获得尽可能多的按钮来下载,因为在'myout'中生成了数据帧。它甚至可能吗?

或者也许可以创建一个downloadButton,允许用户“选择”他/她想要下载的数据框? 非常感谢任何提示 - 因为我不确定如何处理它!

我的代码(我使用:runApp(launch.browser = T)

运行它)
### My ui.R code:

shinyUI(pageWithSidebar(

  headerPanel("My App"),

  sidebarPanel(
    numericInput('NumRuns','Number of runs',value=3,min=3,max=10,step=1),
    br(),
    actionButton(inputId="goButton","Run!"),
    br(),
    br(),
    textInput("downloadData","Save My Data Frame:",value="Data Frame 1"),
    downloadButton('downloadData','Save my file!')

  ),

  mainPanel(
    tabsetPanel(
      tabPanel("Shows the 1st data frame",tableOutput("mydf"))
    )
  )
))


### My 'server.R' code:
shinyServer(function(input,output){


  ### Creating files for displaying and downloading

  myout = reactive({
    if(input$goButton==0) return(NULL)

    nrruns=input$NumRuns
    mylist=NULL
    for(i in 1:nrruns){
      mylist[[i]]<-data.frame(a=rnorm(10),b=runif(10))
      names(mylist)[i]<-paste("dataframe",i,sep="")
    }
    return(mylist)
  })

  # Grabbing only the 1st data frame:
  output$mydf <- renderTable({
    if(input$goButton==0) return(NULL)
    myout()$dataframe1
  })

  # Allowing to download only the 1st data frame:
  output$downloadData <- downloadHandler(
    filename = function() { paste(input$downloadData, " ",Sys.Date(),".csv",sep="") },
    content = function(file) {
      write.csv(myout()$dataframe1,file,row.names=F)
    }
  )

})

1 个答案:

答案 0 :(得分:1)

这篇文章可能会给你答案。

https://groups.google.com/forum/#!msg/shiny-discuss/qGN3jeCbFRY/xOW5qoVrr94J

  

是的,这是可能的。您需要使用uiOutput / renderUI来渲染按钮,每个按钮具有不同的ID(例如downloadData1到downloadDataN)。要动态定义下载处理程序,请使用如下模式:

observe({
  lapply(1:N, function(i) {
    output[[paste0("downloadData", i)]] <- downloadHandler(...)
  })
})
  

如果您的输出名称是动态的,那么您可以分配给输出[[id]]这一点很重要。