Home > Back-end >  bindEvent seems to remove dependencies on inputs
bindEvent seems to remove dependencies on inputs

Time:12-23

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:

  1. App Loads
  2. User selects number of bins
  3. User clicks plot button
  4. Plot is rendered
  5. User changes number of bins
  6. Shiny removes the plot because the bins have changed
  7. User clicks plot button
  8. Plot is rendered

Actual behavior:

  1. App Loads
  2. User selects number of bins
  3. User clicks plot button
  4. Plot is rendered
  5. User changes number of bins
  6. Shiny does nothing -- keeping the stale plot around
  7. User clicks plot button
  8. 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:

enter image description here

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. enter image description here

I suspect this step is what I want to avoid happening: enter image description here

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)
  • Related