I'd like to have a Plot
button that is used to generate an output. This works great. The trouble I'm having is that when I change an input, I'd expect for the plot to become invalid, and for it to stop showing up.
Expected behavior:
- App Loads
- User selects number of bins
- User clicks plot button
- Plot is rendered
- User changes number of bins
- Shiny removes the plot because the bins have changed
- User clicks plot button
- Plot is rendered
Actual behavior:
- App Loads
- User selects number of bins
- User clicks plot button
- Plot is rendered
- User changes number of bins
- Shiny does nothing -- keeping the stale plot around
- User clicks plot button
- Plot is rendered
As you can see in this screenshot, bins have been set to a small value, and the 30 bin histogram is still showing:
When inspecting the dependency graph, I notice that step 5 above, the relationship between input$bins
and bindEvent
becomes grayed out (see image) which ultimately stops output$distPlot
from invalidating and recalculating.
I suspect this step is what I want to avoid happening:
Here's the reprex
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30),
actionButton('plot', 'Plot')
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
)
x = faithful[,2]
# Define server logic required to draw a histogram
server <- function(input, output) {
bins <- reactive({
seq(min(x), max(x), length.out = input$bins 1)
}) %>%
bindEvent(input$plot)
output$distPlot <- renderPlot({
# generate bins based on input$bins from ui.R
# draw the histogram with the specified number of bins
hist(x, breaks = bins(), col = 'darkgray', border = 'white',
xlab = 'Waiting time to next eruption (in mins)',
main = 'Histogram of waiting times')
})
}
# Run the application
shinyApp(ui = ui, server = server)
CodePudding user response:
The desired behaviour can be realized using a reactiveVal
:
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30),
actionButton('plot', 'Plot')
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
)
x = faithful[,2]
# Define server logic required to draw a histogram
server <- function(input, output, session) {
bins <- reactiveVal(NULL)
observeEvent(input$plot, {
bins(seq(min(x), max(x), length.out = input$bins 1))
})
observeEvent(input$bins, {
bins(NULL)
})
output$distPlot <- renderPlot({
req(bins())
# draw the histogram with the specified number of bins
hist(x, breaks = bins(), col = 'darkgray', border = 'white',
xlab = 'Waiting time to next eruption (in mins)',
main = 'Histogram of waiting times')
})
}
# Run the application
shinyApp(ui = ui, server = server)