Reputation: 1293
I have a shiny app with a reactive bit of UI which is used to filter my data. I then use the data for plotting. My reactive bit of UI checks all possible values of a variable, offers them as choices in a selectizeInput
and starts with all of the choices selected. In my actual app changes in the filter can take quite a bit of time to run so I have submitButton
to prevent the app from constantly updating. The only problem is on the initial startup of the app: It loads the choices in to the dynamic UI and selects them, but because further reactivity is blocked by the submitButton
, this information doesn't reach the plot and so it shows an empty plot. All that's needed to get the desired result is hit the sumbitButton
once. Once this is done the app works as desired.
I'm looking for a way to make the plot show initially without having to press the submitButton
. In my following toy example this could probably be done quite easily by replacing the submitButton
with an actionButton
so that not all reactivity is frozen, which seems to be the solution in a lot of problems involving submitButton
s in other question. However, in my actual app there are numerous inputs and sources of reactivity so configuring the actionButton
and capturing all desired effects in observeEvent
s would be quite tedious when the submitButton
does all of this with the only problem being the startup. Are there any other ways I can make the plot show on the first startup but follow the submitButton
behavior from then on?
An example app:
library(shiny)
library(ggplot2)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
uiOutput("Cylselectui"),
submitButton("Apply changes")
),
mainPanel(
plotOutput("Carsplot")
)
)
)
server <- function(input, output) {
output$Carsplot <- renderPlot({
plotdata <- subset(mtcars, cyl %in% input$Cylselection) #Filter based on cyl
ggplot(plotdata, aes(x = mpg, y = hp, colour = factor(cyl))) + #Create plot
geom_point()
})
output$Cylselectui <- renderUI({ #Create the cyl selectize ui based on the values of cyl that are in the data
selectizeInput(
'Cylselection', 'Select by Cylinder',
choices = sort(unique(mtcars$cyl)),
selected = sort(unique(mtcars$cyl)),
multiple = TRUE
)
})
}
shinyApp(ui = ui, server = server)
Upvotes: 3
Views: 852
Reputation: 19544
You can use a reactive
to check whether the input is null (first time) and then provide your defaults values:
Cylselection <- reactive({
if(is.null(input$Cylselection))
sort(unique(mtcars$cyl))
else
input$Cylselection})
output$Carsplot <- renderPlot({
plotdata <- subset(mtcars, cyl %in% Cylselection()) #Filter based on cyl
ggplot(plotdata, aes(x = mpg, y = hp, colour = factor(cyl))) + #Create plot
geom_point()
})
More elegant is to put your data subset in the reactive:
plotdata <- reactive({
if(is.null(input$Cylselection))
mtcars
else
subset(mtcars, cyl %in% input$Cylselection)})
output$Carsplot <- renderPlot({
ggplot(plotdata(), aes(x = mpg, y = hp, colour = factor(cyl))) + #Create plot
geom_point()
})
Upvotes: 2