Doug Fir
Doug Fir

Reputation: 21302

using a function to renderUI(selectInput()) in Shiny app

Here's server.r

server <- function(input, output) {
  output$species <- renderUI({
     selectInput("species", 
                 label = "blah", 
                 choices = as.list(unique(iris$Species)))
      })
}

Then over in ui.r

ui <- fluidPage(
   fluidRow(        
       uiOutput("species")
)

This works as expected, a drop down select input appears like this: enter image description here

Since I have multiple features I need to create a similar filter for in my actual data frame, I tried to do the same with a function:

In server.r

  outputFilters <- function(id, df) {
    output$id <- renderUI({
     selectInput(id, 
                 label = "blah", 
                 choices = as.list(unique(df$id)))
      })
  }

outputFilters("species", iris)

Then in ui.r same as before uiOutput("species")

However, now no drop down appears. Presumably my function is flawed. How can I use a function to generate the drop downs?

Upvotes: 3

Views: 3196

Answers (2)

Florian
Florian

Reputation: 25425

Note that you could also do without a separate function in this case, by wrapping the desired ui component in lapply, or putting the lapply within the uiOutput to create all inputs at once, below is an example for the both two cases. Hope this helps!

ibrary(shiny)

ui <- fluidPage(
  uiOutput('Species'),
  uiOutput('Sepal.Length'),
  h2('All inputs: '),
  uiOutput('my_inputs')
)


server <- function(input, output) {

  # Use lapply to create multiple uiOutputs.
  lapply(colnames(iris), function(x){
    output[[x]] <- renderUI({
      selectInput(paste0('input_',x), 
                  label = x, 
                  choices = as.list(unique(iris[['x']])))
    })
  })

  # Create all dropdown's at once.
  output$my_inputs <- renderUI({
    lapply(colnames(iris), function(x){
      selectInput(paste0('input_',x), 
                  label = x, 
                  choices = as.list(unique(iris)))
    })
  })

}

shinyApp(ui, server)

Upvotes: 3

zacdav
zacdav

Reputation: 4671

Your problem is that each UI element needs its own id in the output

 outputFilters <- function(id, df) {
    output[[id]] <- renderUI({
     selectInput(id, 
                 label = "blah", 
                 choices = as.list(unique(df[[id]])))
      })
  }

now as long as id is a string in the function input it should generate the output element and you can refer with said id

You could then even use lapply to iterate over numerous, kind of how florian suggests.

Upvotes: 2

Related Questions