How to use bindCache with action button

Hi all,

Wondering if someone has ever used bindCache with an action button.

I have an eventReactive where the event is a input$go (action bttn). In my bigger app this event reactive depends on more reactives and inputs (other than input$go) and represents a long calculation. (Hence the eventReactive as I want to make sure that the user sure about the selectInput selection.

I would like to cache the object that comes out of the eventReactive (to avoid running the long calculation again if the user selects the same selectInputs twice.
Therefore, all the inputs (other than input$go) should I guess be the cache key.

However, I have observed that the eventReactive %>% bindCache is not allows and if I cache the next reactive in the reactlog, shiny still executes the eventReactive. See code below.

UI

# Define UI for dataset viewer app ----
ui <- fluidPage(
    
    # App title ----
    titlePanel("Reactivity"),
    
    # Sidebar layout with input and output definitions ----
    sidebarLayout(
        
        # Sidebar panel for inputs ----
        sidebarPanel(
            
            # Input: Text for providing a caption ----
            # Note: Changes made to the caption in the textInput control
            # are updated in the output area immediately as you type
            textInput(inputId = "caption",
                      label = "Caption:",
                      value = "Data Summary"),
            
            # Input: Selector for choosing dataset ----
            selectInput(inputId = "dataset",
                        label = "Choose a dataset:",
                        choices = c("rock", "pressure", "cars")),
            
            # Input: Numeric entry for number of obs to view ----
            numericInput(inputId = "obs",
                         label = "Number of observations to view:",
                         value = 10),
            
            # add button 
            actionBttn(inputId = 'go',
                       label   = 'Go')
            
        ),
        
        # Main panel for displaying outputs ----
        mainPanel(
            
            # Output: Formatted text for caption ----
            h3(textOutput("caption", container = span)),
            
            # Output: Verbatim text for data summary ----
            verbatimTextOutput("summary"),
            
            # Output: HTML table with requested number of observations ----
            tableOutput("view")
            
        )
    )
)

Server

server <- function(input, output) {
    
    # Return the requested dataset ----
    # By declaring datasetInput as a reactive expression we ensure
    # that:
    #
    # 1. It is only called when the inputs it depends on changes
    # 2. The computation and result are shared by all the callers,
    #    i.e. it only executes a single time
    # THIS EVENT REACTIVE REPRESENTS A LONG CALCULATION! Hence the sys.sleep(5)
    datasetInput <- eventReactive(input$go, {
        Sys.sleep(5)
        return(
            switch(input$dataset,
                  "rock" = rock,
                  "pressure" = pressure,
                  "cars" = cars)
        )
    }) 
    
    # Create caption ----
    # The output$caption is computed based on a reactive expression
    # that returns input$caption. When the user changes the
    # "caption" field:
    #
    # 1. This function is automatically called to recompute the output
    # 2. New caption is pushed back to the browser for re-display
    #
    # Note that because the data-oriented reactive expressions
    # below don't depend on input$caption, those expressions are
    # NOT called when input$caption changes
    output$caption <- renderText({
        input$caption
    }) 
    
    # Generate a summary of the dataset ----
    # The output$summary depends on the datasetInput reactive
    # expression, so will be re-executed whenever datasetInput is
    # invalidated, i.e. whenever the input$dataset changes
    output$summary <- renderPrint({
        dataset <- datasetInput()
        summary(dataset)
    }) %>%
        bindCache(datasetInput(), cache = "session")
    
    # Show the first "n" observations ----
    # The output$view depends on both the databaseInput reactive
    # expression and input$obs, so it will be re-executed whenever
    # input$dataset or input$obs is changed
    output$view <- renderTable({
        head(datasetInput(), n = input$obs)
    }) %>%
        bindCache(datasetInput(), input$obs, cache = "session")
    
}

Might this be because the datasetInput() gets invalidated after I click the go button? How can I avoid that?
Many thanks for your help!!!

I should think it is allowed. Do you get some error?

Yes I get an error as you cant use bindEvent with bindCache. At least that is what it says. :wink:

Warning: Error in bindCache.reactive.event: Can't call bindCache() after calling bindEvent() on an object. Maybe you wanted to call bindEvent() after bindCache()?
  58: stop
  57: bindCache.reactive.event
  55: function_list[[k]]
  53: freduce
  52: _fseq
  51: eval
  50: eval
  48: %>%
  47: server [#4]
Error in bindCache.reactive.event(., input$dataset, cache = "session") : 
  Can't call bindCache() after calling bindEvent() on an object. Maybe you wanted to call bindEvent() after bindCache()?

Got it!
The solution is to replace

eventReactive 

with

reactive () %>% bindEvent() 

as they are equivalent.

And then sneak bindCache in between ; )
Solution:

 # THIS EVENT REACTIVE REPRESENTS A LONG CALCULATION! Hence the sys.sleep(5)
    datasetInput <- reactive({
        Sys.sleep(5)
        return(
            switch(input$dataset,
                  "rock" = rock,
                  "pressure" = pressure,
                  "cars" = cars)
        )
    }) %>% bindCache(input$dataset, cache = "session") %>% bindEvent(input$go)

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.