TheComeOnMan
TheComeOnMan

Reputation: 12905

Rendering Inside ObserveEvent (Dynamic Plot Generation)

I'm trying to recreate https://gist.github.com/wch/5436415/ but by adding plots through a button. I think this needs me to modify the server.r code on the link along these lines (the chartname related variable are created through reactiveValues) -

observeEvent(
      input$buttonAddData, 
      {
         ...
         newchartname = c(newchartname,newchartname)
         output[[newchartname]] = renderPlot({
            ...
         })
      }
)

output$plots = renderUI(
      {

         plot_output_list <- lapply(
            seq(length(allthechartnames)), 
            function(i) {
               plotname <- paste(
                  isolate(allthechartnames)[i]
               )
               plotOutput(plotname, height = 280, width = 250)
               cat(plotname,'\n')
            }
         )

         # Convert the list to a tagList - this is necessary for the list of items
         # to display properly.
         do.call(tagList, plot_output_list)

      }
   )

But this seems to not enter the original loop of creating the chart itself inside the observeEvent which results in no charts inside the renderUI block.

Any tips?

Upvotes: 3

Views: 7531

Answers (1)

DeanAttali
DeanAttali

Reputation: 26363

I don't really understand the code in your question so I kind of ignored it and just took Winston's code from the gist and made it work with a button instead of a slider. I hope this is what you meant? Also, I did have to use render inside an observer which I'm not happy about :/

runApp(shinyApp(
  ui = fluidPage(
    headerPanel("Dynamic number of plots"),

    mainPanel(
      actionButton("addplot", "Add plot"),
      uiOutput("plots")
    )
  ),
  server = function(input, output, session) {

    # A variable that keeps track of the number of plots we have
    values <- reactiveValues(
      numPlots = 1
    )

    # Whenever the "add plot" button is pressed, increment num plots by 1
    observeEvent(input$addplot, {
      values$numPlots <- values$numPlots + 1
    })

    # Dynamically generate the UI that creates all the plots
    output$plots <- renderUI({
      # Create a list of `plotOutput` objects (for each plot, use a unique ID)
      plot_output_list <- lapply(1:values$numPlots, function(i) {
        plotname <- paste("plot", i, sep="")
        plotOutput(plotname, height = 280, width = 250)
      })

      # Place all the plot outputs inside a shiny `tagList()`
      do.call(tagList, plot_output_list)
    })

    # Every time the number of plots changes (button is clicked),
    # re-generate the render functions for all the plots
    observeEvent(values$numPlots, {
      for (i in 1:values$numPlots) {
        local({
          my_i <- i
          plotname <- paste("plot", my_i, sep="")

          output[[plotname]] <- renderPlot({
            plot(1:my_i, 1:my_i,
                 xlim = c(1, values$numPlots),
                 ylim = c(1, values$numPlots),
                 main = paste("1:", my_i, ".  n is ", values$numPlots, sep = "")
            )
          })
        })
      }
    })
  }
))

Hope that helps

Upvotes: 8

Related Questions