在闪亮页面中使用可变数量的输入字段

时间:2015-04-22 07:44:06

标签: r shiny rstudio

我的问题如下:

我有一个闪亮的应用程序,它根据用户输入显示可变数量的输出元素(例如,详见:dynamically add plots to web page using shiny)。

但是,我还想在每个输出元素中添加一个输入元素,允许用户为输出指定一些修饰符(例如,让用户选择将每个元素视为一个图或一个表,但是可以推广对可变数量的输出进行任何修改。)

我认为最简单的方法是使用我希望用户拥有的选项为每个元素添加一个selectInput元素。 我的问题是,每次渲染页面时,selectInput元素似乎都会恢复到它们的初始值,因此更改它们没有任何效果(实际上,它们确实有效果,但它们会被重置,效果是收归)。

以下代码重现了该问题(根据@skasch对上述问题的回答进行了修改):

server.R

library(shiny)
max_plots <- 5

shinyServer(function(input, output) {

# Insert the right number of plot output objects into the web page
output$plots <- renderUI({
  plot_output_list <- lapply(1:input$n, function(i) {
     modifier <- paste("select",i,sep="")
     plotname <- paste("plot", i, sep="")
     plottitle <- paste("plottitle", i, sep="")
     tablename <- paste("tablename", i, sep="")

     # By default I display a plot
     disp <- plotOutput(plotname, height = 280, width = 250)  
     # modifier may not be in the input if this is the first time the element is displayed
     if(modifier %in% names(input) && input[[modifier]] == "table") {
       disp = tableOutput(tablename)
     }
     # Make the output element display properly:
     tagList(
       textOutput(plottitle, container = h3),
       uiOutput(modifier),
       disp)
   })    
   # Convert the list to a tagList - this is necessary for the list of items
   # to display properly.
   do.call(tagList, plot_output_list)
})

# Call renderPlot for each one. Plots are only actually generated when they
# are visible on the web page.
for (i in 1:max_plots) {
    # Need local so that each item gets its own number. Without it, the value
    # of i in the renderPlot() will be the same across all instances, because
    # of when the expression is evaluated.
    local({
        my_i <- i
        modifier <- paste("select",i,sep="")
        plotname <- paste("plot", my_i, sep="")
        plottitle <- paste("plottitle", my_i, sep="")
        tablename <- paste("tablename", my_i, sep="")

        output[[plotname]] <- renderPlot({
        plot(1:my_i, 1:my_i, xlim = c(1, max_plots), ylim = c(1, max_plots), main = paste("1:", my_i, ".  n is ", input$n, sep = ""))
        })
        output[[plottitle]] <- renderText({paste("1:", my_i, ".  n is ", input$n, sep = "")
        })
        output[[tablename]] <- renderTable({table(x = 1:my_i, y = 1:my_i)
        })
        # I suspect the problem is the re-evaluation of this part that resets the "selected" field
        output[[modifier]] <- renderUI({selectInput(
                                          inputId = modifier,
                                          label="select how to display",
                                          choices = c("plot","table"),
                                          selected = 1)})
    })
}
})

ui.r

library(shiny)
shinyUI(pageWithSidebar(

  headerPanel("Dynamic number of plots"),

    sidebarPanel(
      sliderInput("n", "Number of plots", value=1, min=1, max=5)
    ),

    mainPanel(
      uiOutput("plots") # This is the dynamic UI for the plots
    )
))

1 个答案:

答案 0 :(得分:1)

虽然我发现它不是一个理想的解决方案,但分配:

output[[modifier]] <- renderUI({selectInput(
                                      inputId = modifier,
                                      label="select how to display",
                                      choices = c("plot","table"),
                                      selected = input[[modifier]])})

解决了这个问题,虽然我很乐意得到一个更好的解决方案(特别是每次重新避免构造输入对象的解决方案)。