3
votes

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?

2

2 Answers

2
votes

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)
2
votes

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.