0
votes

In Shiny, I create a UI dynamically in the server element using renderUI and tagList, and then display it using uiOutput. It works, but I'd like to break up the contents of uiOutput into columns. How do I do that?

Here's the (slightly abbreviated) Dynamic UI example from the Shiny gallery. Note how output$ui contains a tagList that ends up displaying as one column, but I want it to display as two.

Note that I can't call column inside renderUI.

library(shiny)

server <- shinyServer(function(input, output) {
  output$ui <- renderUI({
    if (is.null(input$input_type)) {return()}
    tagList(list(div("Want this to be left column"),
         switch(input$input_type,
           "slider" = sliderInput("dynamic", "Want this to be right column",
                                  min = 1, max = 20, value = 10),
           "text" = textInput("dynamic", "Want this to be right column",
                              value = "starting value"),
           "numeric" =  numericInput("dynamic", "Want this to be right column",
                                     value = 12),
           "checkbox" = checkboxInput("dynamic", "Want this to be right column",
                                      value = TRUE))))
  })
  output$input_type_text <- renderText({input$input_type})
  output$dynamic_value <- renderPrint({str(input$dynamic)})
})

ui <- shinyUI(fluidPage(
  titlePanel("Dynamically generated user interface components"),
  wellPanel(selectInput("input_type", "Input type",
                        c("slider", "text", "numeric", "checkbox")
  )),
  wellPanel(uiOutput("ui")),
  wellPanel(
    tags$p("Input type:"),
    verbatimTextOutput("input_type_text"),
    tags$p("Dynamic input value:"),
    verbatimTextOutput("dynamic_value")
  )
))

shinyApp(ui = ui, server = server)
1

1 Answers

1
votes

Instead of wrapping div and a selected widget into list and then into tagList (you don't need them both - one of them suffice)

tagList(list(div("Want this to be left column"), switch(...) ...)

create fluidRow and add two columns - one with the div and the another with switch:

fluidRow(column(6, div("Want this to be left column")),
         column(6, switch(input$input_type,
                        "slider" = sliderInput("dynamic", "Want this to be right column",
                                               min = 1, max = 20, value = 10),
                        "text" = textInput("dynamic", "Want this to be right column",
                                           value = "starting value"),
                        "numeric" =  numericInput("dynamic", "Want this to be right column",
                                                  value = 12),
                        "checkbox" = checkboxInput("dynamic", "Want this to be right column",
                                                   value = TRUE)
                  )
          )
        )

Full example:

library(shiny)

server <- shinyServer(function(input, output) {
  output$ui <- renderUI({
    if (is.null(input$input_type)) {return()}
    fluidRow(column(6, div("Want this to be left column")),
             column(6, switch(input$input_type,
                              "slider" = sliderInput("dynamic", "Want this to be right column",
                                                     min = 1, max = 20, value = 10),
                              "text" = textInput("dynamic", "Want this to be right column",
                                                 value = "starting value"),
                              "numeric" =  numericInput("dynamic", "Want this to be right column",
                                                        value = 12),
                              "checkbox" = checkboxInput("dynamic", "Want this to be right column",
                                                         value = TRUE)
             )
             )
    )
  })
  output$input_type_text <- renderText({input$input_type})
  output$dynamic_value <- renderPrint({str(input$dynamic)})
})

ui <- shinyUI(fluidPage(
  titlePanel("Dynamically generated user interface components"),
  wellPanel(selectInput("input_type", "Input type",
                        c("slider", "text", "numeric", "checkbox")
  )),
  wellPanel(uiOutput("ui")),
  wellPanel(
    tags$p("Input type:"),
    verbatimTextOutput("input_type_text"),
    tags$p("Dynamic input value:"),
    verbatimTextOutput("dynamic_value")
  )
))

shinyApp(ui = ui, server = server)