Reputation: 1111
As the title suggests, I wish to make a dynamically created UI object (using renderUI
) which can be further manipulated later in the Shiny App.
In the below reprex, I have a toy application which allows a user to filter the iris
dataset based on the sepal width. Depending on the range the user selects, I then generate a checkbox list of all the unique species within that sepal width range.
My question is: how can I make the app tell me which species' checkbox has been selected once the user has filtered the table? For example, at the default app settings when the sepal width range is between 1 and 2, only one species is satisfies the filter requirement (versicolor). When a user checks the versicolor box, I would like the app to update to tell me that versicolor has been selected.
Similarly, when the sepal width range is greater (and more species are then included in the dynamically generated checkbox list) I would like the UI to update again to tell me which species was selected (either 1, 2 or all 3 species).
The basic workflow in my head is:
(1) User filters Dataset (2) Displayed Table Updates Based on Filter (3) App Generates Checkbox List of Unique Species (4) User Clicks on Species, Species Name is Presented on-screen.
library(shiny)
library(DT)
library(dplyr)
ui <- basicPage(
fluidRow(
uiOutput("ui"),
sliderInput("slider", "Sepal Width", min = 0, max=20, value=c(1:2)),
tableOutput("data")
),
)
server <- function(input, output){
data("iris")
filtered<-reactive({
iris %>% filter(`Sepal.Width` %in% input$slider[1]:input$slider[2])
})
output$data<-renderTable({
filtered()
})
output$ui<-renderUI({
species<-filtered()
checkboxGroupInput(inputId = 'occurence_checkboxes', label = 'Species', choices = unique(species$Species))
})
}
shinyApp(ui, server)
Upvotes: 2
Views: 1194
Reputation: 20399
This should do the trick:
library(shiny)
library(dplyr)
ui <- basicPage(
fluidRow(
uiOutput("ui"),
sliderInput("slider", "Sepal Width", min = 0, max=20, value = 1:2),
tableOutput("data")
)
)
server <- function(input, output){
get_width_filter <- reactive({
iris %>% filter(between(Sepal.Width, input$slider[1], input$slider[2]))
})
get_ovl_filter <- reactive({
get_width_filter() %>%
filter(Species %in% input$occurence_checkboxes)
})
output$data <- renderTable({
get_ovl_filter()
})
output$ui <- renderUI({
choices <- get_width_filter() %>% pull(Species) %>% unique()
checkboxGroupInput("occurence_checkboxes",
"Species",
choices = choices,
selected = choices)
})
}
shinyApp(ui, server)
Explanation
We need to split the filtered
routine in 2 parts: 1 which applies just the width filter and one which also incorporates the species filter. You can access the dynamically created checkbox via the name which you you use in your renderUI
function. The reason that we have to split the filter reactive is that otherwise the renderUI
would take dependence on the checkbox itself which we want to avoid.
Update
I just read that you just wanted to return the values of the checkbox not use it to filter. But I guess that this should be clear now, just use input$occurence_checkboxes
whereever you need it.
Upvotes: 2