How to update an actionButton while computing in R shiny

120 views Asked by At

I'm trying to create an action button that has the following behavior once clicked:

  • gets disabled
  • changes label to temporary value while an arbitrary computation is ongoing
  • gets re-enabled and reverts back to initial label once computation is over

Essentially, I want to create something very similar to this.

My problem is that I cannot get the button to temporarily change label during computation.

Here's the code I tried:


library(shiny)
library(shinyjs)

ui <- fluidPage(
  
  shinyjs::useShinyjs(),
  
  # create action button
  fluidRow(
    column(12, align = "center",
           actionButton("button_analysis", label = "Label 1", icon = icon("rocket"))
    )
  )
  
)

server <- function(input, output, session) {
  
  observe({
    
    # disable button
    shinyjs::disable("button_analysis")
    
    # update button not working
    updateActionButton(session, inputId = "button_analysis", label = "temporary label", icon = icon("sync", class = "fa-spin"))
    
    # fake computation
    Sys.sleep(2)
    
    # enable button and change label after fake computation
    on.exit({
      shinyjs::enable("button_analysis")
      updateActionButton(session, "button_analysis", label = "Label 2", icon = icon("rocket"))
    })
    
  }) %>%
    bindEvent(input$button_analysis)
  
}

shinyApp(ui, server)

Could anyone explain to me why the updateActionButton() works while exiting the observeEvent, but not while inside it?

1

There are 1 answers

2
Vasileios Tsiamis On

I just experienced the same problem. It is probably too late for your case but here is a working example:

library(shiny)
library(shinyjs)

ui <- shiny::fluidPage(
  
  shinyjs::useShinyjs(),
  
  # Add action button.
  shiny::fluidRow(
    shiny::column(width = 12,
                  align = "center",
                  shiny::actionButton("button_analysis", label = "Label 1", icon = shiny::icon("rocket"))
    )
  )
  
)

server <- function(input, output, session) {
  
  shiny::observeEvent(input$button_analysis, {
    
    # Disable button.
    shinyjs::disable("button_analysis")
    
    # Update button.
    shiny::updateActionButton(session, inputId = "button_analysis", label = "temporary label", icon = shiny::icon("sync", class = "fa-spin"))
    
    # Add delay. 
    shinyjs::delay(ms = 100, expr = {
      
      # Fake computation.
      Sys.sleep(time = 2)
      
      # Re-enable button.
      shinyjs::enable("button_analysis")
      
      # Update button.
      shiny::updateActionButton(session, "button_analysis", label = "Label 2", icon = shiny::icon("rocket"))
      
    })
    
  })
  
}

shiny::shinyApp(ui, server)

Simply, there is no time to update the action button and thus a delay should be added, as it is suggested here too. The tricky part for me was where to place the calculations, and that is after we give some time to the button to be updated, hence within the delay chunk. I hope that answers your question.

I also think that the question "How to update action button label with updateActionButton in R shiny" does not fit to the description of the matter. This could be answered by the following chunk:

shiny::observeEvent(input$button_analysis, {

  # Update button.
  shiny::updateActionButton(session, inputId = "button_analysis", label = "temporary label", icon = shiny::icon("sync", class = "fa-spin"))

})

A title like "How to update an actionButton while calculating in R shiny" or "How to turn an actionButton into a loading button in R shiny" or something similar, could fit better to the issue.