How to position multiple dynamically added ui elements in shiny r


#1

I am new to the Shiny package with R. I want to plot a dynamic number of plots and be able to control each one of them individually based on the user input for each plot. This means that it will have a set of input that will dynamically pop up for each plot.

I know from this code here that one can dynamically add plots. From the code mentioned here, I was able to dynamically generate the inputs too. However, I cannot place them side by side.

When I try to do for two plots, I get the following. What I want is shown using the arrows:

Could you help me with this? My code is as below

server.R

max_plots <- 50

shinyServer(function(input, output) {
  
  # Insert the right number of plot output objects into the web page
  output$plots <- renderUI({
    # radioButtons(inputId = paste0("mVariable",i), label = paste0("mVariable",i), choices = c("A","B","C"))
    plot_output_list <- lapply(1:input$n, function(i) {
    plotname <- paste("plot", i, sep="")
    plotOutput(plotname, height = 280, width = 250)

    })
    
    # Convert the list to a tagList - this is necessary for the list of items
    # to display properly.
    do.call(tagList, plot_output_list)
  })
  
output$Dynamic <- renderUI({
  dynamic_selection_list <- lapply(1:input$n, function(i) {
    radioButtons(inputId = paste0("mVariable",i), label = paste0("mVariable",i), choices = c("A","B","C"))
  })
  do.call(tagList, dynamic_selection_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
      plotname <- paste("plot", 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 = "")
             
        )
      })
    })
  }
})

ui.R

shinyUI(pageWithSidebar(
  
  headerPanel("Dynamic number of plots"),
  
  sidebarPanel(
    sliderInput("n", "Number of plots", value=1, min=1, max=5)
  ),
  
  mainPanel(
    # This is the dynamic UI for the plots
    uiOutput("plots"),
    uiOutput("Dynamic")
  )
))

#2

You could have a single renderUI():

library(shiny)

max_plots <- 50

server <- function(input, output) {
  
  output$plots_and_radios <- renderUI({
    plot_and_radio_output_list <- lapply(1:input$n, function(i) {
      plotname <- paste("plot", i, sep="")
      list(
        plotOutput(plotname, height = 280, width = 250),
        radioButtons(inputId = paste0("mVariable",i), label = paste0("mVariable",i),
                     choices = c("A","B","C"))
      )
    })
    do.call(tagList, unlist(plot_and_radio_output_list, recursive = FALSE))
  })
  
  for (i in 1:max_plots) {
    local({
      my_i <- i
      plotname <- paste("plot", 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 = "")
        )
      })
    })
  }
  
}

ui <- pageWithSidebar(
  
  headerPanel("Dynamic number of plots"),
  
  sidebarPanel(
    sliderInput("n", "Number of plots", value=1, min=1, max=5)
  ),
  
  mainPanel(
    uiOutput("plots_and_radios")
  )
)

shinyApp(ui, server)

#3

This code was helpful. Thank you for the help. However, the follow up question is if I change the alphabets from A, B and C to 20, 40 and 50 and I want to replace the max_plots in the plotoutput function, how do i do that? I am not able to use input$choices or something like that.