mosk915
mosk915

Reputation: 814

Is it possible to pass an input to a UI function in Shiny?

I want to create a dynamic UI in my shiny app where the column widths of various panels can be specified by the user. Is it possible to render the column width in the server and pass it to the UI as an output or does the width need to be hardcoded in the UI?

Upvotes: 0

Views: 72

Answers (1)

Adam Birenbaum
Adam Birenbaum

Reputation: 950

Here's a single file script that lets the user choose the size of two panels. There were two challenges that I didn't see at first, and probably could have been handled in a cleaner way. They are:

  1. The user defined widths input box is within the panel whose width is defined by that input. Basically a chicken vs. the egg situation. You need to have some method of setting the width of the panels to some initial value when first run. I did it within that ifelse(...) function.
  2. If one panel's width is changed to be more than 6, then the other needs to shrink so that the sum is not greater than 12.

    old_panel_width1 <<- 6
    old_panel_width2 <<- 6
    
    
    ui <- bootstrapPage(
      uiOutput("dynamic_panels")
    
     )
    
    server <- function(input, output) {
    
     n1 <- reactive(input$n1)
     n2 <- reactive(input$n2)
    
     output$dynamic_panels <- renderUI({
    
    #assigns an initial value of 6 when first loaded
    panel_width1 <<- ifelse(is.null(input$n1), 6, n1())
    panel_width2 <<- ifelse(is.null(input$n2), 6, n2())
    
    #one way of detecting whether panel 1 or 2 was changed and then adjusting the sizes so that the sum < 12
    if (panel_width1!= old_panel_width1){
      if (panel_width1 > 6 && sum(panel_width1,panel_width2) > 12) panel_width2 <<- 12 - panel_width1
      old_panel_width1 <<- panel_width1
    }
    
    if (panel_width2!= old_panel_width2){
      if (panel_width2 > 6 && sum(panel_width1,panel_width2) > 12) panel_width1 <<- 12 - panel_width2
      old_panel_width2 <<- panel_width2
    }
    
    
    
    fluidRow(
    column(width = panel_width1,
           numericInput('n1', 'size of panel 1', min = 1, max = 11,value = panel_width1),
           plotOutput("plot1")
           ),
    column(width = panel_width2,
           numericInput('n2', 'size of panel 2',min = 1, max = 11,value = panel_width2),
           plotOutput("plot2")
           )
     )
    
    })
    
    output$plot1 <- renderPlot(hist(runif(100)))
    output$plot2 <- renderPlot(hist(runif(100)))
    
    }
    
    # Return a Shiny app object
    shinyApp(ui = ui,server = server)
    

Upvotes: 1

Related Questions