Search code examples
rshinyshiny-servershinydashboard

How to condition a recalculation of a table to an actionButton click in RShiny app


I have the following very simple app

funSolver <- function(server,currencyList,tenorList,tailList) {

return(do.call(rbind,lapply(currencyList,function(ccy) {
    return(do.call(rbind,lapply(tenorList,function(tenor) {
        return(do.call(rbind,lapply(tailList,function(myTail) {
            a <- 0
            b <- 10
            d <- 25
            e <- 35
            return(data.frame(ccy=ccy,tenor=tenor,tail=myTail,a=a,b=b,d=d,e=e))
        })))
    })))
})))
}


ui <- fluidPage(

titlePanel("Carry Selector"),
sidebarPanel(
    selectInput(inputId = 'serverListInput',label = 'Server', choices=as.list(paste("adsg-",c("l01","ln01","l02","ln02"),sep="")),multiple = FALSE,selectize = TRUE),
    selectInput(inputId = 'currencyListInput',label = 'blabla', choices=list("blabla1","blabla2","blabla3"),multiple = TRUE,selectize = TRUE),
    fluidRow(
        column(6,selectInput(inputId = 'tenorListInput',label = 'Tenors', choices=as.list(c("All",paste(c(1,3,6),"m",sep=""),paste(c(seq(1,9),seq(10,30,5)),"y",sep=""))),multiple = TRUE,selectize = TRUE)),
        column(6,selectInput(inputId = 'tailListInput',label = 'Tails', choices=as.list(c("All",paste(c(1,2,3,5,7,10,15,20),"y",sep=""))),multiple = TRUE,selectize = TRUE))
    ),
    actionButton(inputId = 'launchCalcButton',label = 'Launch Calc')
),
mainPanel(
    fluidRow(
        column(12,dataTableOutput(outputId = 'table'))
    )
)
)

server <- function(input,output){
observeEvent(input$launchCalcButton, {  
    output$table <- renderDataTable({
        datatable(funSolver(input$serverListInput,input$currencyListInput,input$tenorListInput,input$tailListInput))
    })
})
}

app = shinyApp(ui,server)
runApp(app,port=3250,host='0.0.0.0')

You choose a few parameters and click on the button to show the table generated by the funSolver function. I have wrapped the button call into an observeEvent so the table is generated only when you click. I do not understand why, if you change parameters after the button is first clicked, the table gets updated even though I have not clicked the button.

Q1 : Is that behavior expected ?

Q2 : If it is, how to do what I want to do within a shiny app (table refreshed only when the button is clicked on, not when the parameters are updated) ?

All help appreciated


Solution

  • You added the render function inside the observe event part which means it will run each time the dependencies change within this event. Looking at ?observeEvent gives you a very nice method to get what you want:

    EDIT

    I played a bit with the selectinput and button options and found out it is actually due to the multiple=TRUE argument (I believe). For some reason, this argument overrules the input button dependency in observeEvent. The version below with eventReactive however does work:

    server <- function(input,output){
      df = eventReactive(input$launchCalcButton, {  
           data.table(funSolver(input$serverListInput,input$currencyListInput,input$tenorListInput,input$tailListInput))
      })
    
      output$table <- renderDataTable({
        df()
      })
    }