Disable actionbutton until file upload is complete

I am in need of a part of script where shiny disables an actionbutton only when it detects a file is being uploaded, then re-enables it when upload is completed. Users will have the option to continue through the app without any file upload. Aim is to prevent user to proceed when file upload is started but not yet finished. Below is a minimal example, which doesn't work.

library(shiny)
library(shinyjs)

ui <- fluidPage(
  titlePanel("Disable Action Button while File is uploading"),
  fileInput(
    inputId = "MyFiles",
    label = "Upload files"
  ),
  mainPanel(
    shinyjs::useShinyjs(),
    actionButton("ActionButton","Go")
  )
)

server <- function(input, output) {
  output$fileUploadTest <- reactive({
    shinyjs::disable('ActionButton')
    Sys.sleep(2)
    shinyjs::enable('ActionButton')
    
    return(!is.null(input$MyFiles))
    
  })
  
  outputOptions(output, 'fileUploadTest', suspendWhenHidden=FALSE)
}

shinyApp(ui = ui, server = server)

A shiny expert can correct me but I don't think there's a good way to do this in just R.
I don't think anything get's invalidated until after the file upload is done.

From the javascript side, it's easy to add an event listener when the file is being uploaded.
Onchange is what you want specifically.
This shiny article shows how to set a reactive value from javascript.
This event would trigger the disabling of the button.
Then you can use shiny's normal behavior to enable the button after the file is uploaded successful.

1 Like

I think this does what is wanted. I set the sleep time to 5s to make it painfully obvious. That slows the enabling of the ActionButton on app start up.

As I understand shiny, output$fileUploadTest only gets executed if some reference inside of it gets invalidated, so I made a reference to input$MyFiles.

library(shiny)
library(shinyjs)

ui <- fluidPage(
  titlePanel("Disable Action Button while File is uploading"),
  fileInput(
    inputId = "MyFiles",
    label = "Upload files"
  ),
  mainPanel(
    shinyjs::useShinyjs(),
    actionButton("ActionButton","Go")
  )
)

server <- function(input, output) {
  output$fileUploadTest <- reactive({
    shinyjs::disable('ActionButton')
    FileInfo <- input$MyFiles
    Sys.sleep(5)
    shinyjs::enable('ActionButton')
    
    return(!is.null(input$MyFiles))
    
  })
  
  outputOptions(output, 'fileUploadTest', suspendWhenHidden=FALSE)
}

shinyApp(ui = ui, server = server)
1 Like

@FJCC

Thanks! The code disables action button completely, not enabling it back even with file upload. Maybe it is because some crosstalk within the whole script.

@lxy009

Working on this! Thank you, will let know if I can manage to implement a version of the example on article

I have seen people work with examples below. I tried to modify them to fit my situation, having a hard time with little JS knowledge. Any tips?

Taken from:

ui <- fluidPage(
    tags$script(src="fileInput_text.js"),
    fileInput('uploaded', 'Data Upload')
)

shinyApp(ui = ui, server = function(input, output) {})

fileInput_text.js

$(document).ready(function(){
  $('#uploaded_progress').on("DOMSubtreeModified",function(){

    var target = $('#uploaded_progress').children()[0];
    if(target.innerHTML === "Upload complete"){
        console.log('Change')
        target.innerHTML = 'YOUR TEXT HERE';      
    }

  });
});

Taken from:

library(shiny)

jscode <- '
$("#loginbutton").on("click", function(){
  Shiny.onInputChange("buttonClicked", Math.random());
})
'

ui <- fluidPage(
  actionButton("loginbutton", "Login"),
  singleton(tags$script(HTML(jscode)))
)

server <- function(input, output){
  observeEvent(input$buttonClicked, {
    print("YEAH")
  })
}

shinyApp(ui = ui, server = server)

Hi @alptaciroglu. I assume that you need to load a table. You can disable the button before the table finish loading.

library(shiny)
library(shinyjs)

ui <- fluidPage(
  titlePanel("Disable Action Button while File is uploading"),
  fileInput(
    inputId = "MyFiles",
    label = "Upload files"
  ),
  mainPanel(
    shinyjs::useShinyjs(),
    actionButton("ActionButton","Go")
  )
)

server <- function(input, output) {
  # output$fileUploadTest <- reactive({
  #   shinyjs::disable('ActionButton')
  #   Sys.sleep(2)
  #   shinyjs::enable('ActionButton')
  #   
  #   return(!is.null(input$MyFiles))
  #   
  # })
  # 
  # outputOptions(output, 'fileUploadTest', suspendWhenHidden=FALSE)
  
  vals <- reactiveValues()
  
  observeEvent(input$ActionButton,
               {
                 req(input$MyFiles$datapath)
                 vals$data <- NULL
                 disable("ActionButton")
                 vals$data <- read.table(input$MyFiles$datapath)
               })
  
  observe(
    {
      req(vals$data)
      enable("ActionButton")
    }
  )
}

shinyApp(ui = ui, server = server)

Hello @raytong,

Thanks for the code! In the app, users have the option to proceed without any data upload. What I need is ( also mentioned in the OP ), if user decides to upload a data, app should limit the user to wait for the upload to finish. Thus, disable the "ActionButton" while upload is in progress.

You mean the button is not for trigger the upload but the fileInput. Right? If yes, just change the observeEvent script.

  observeEvent(input$MyFiles$datapath,
               {
                 vals$data <- NULL
                 disable("ActionButton")
                 vals$data <- read.table(input$MyFiles$datapath)
               })
1 Like

Action Button is to proceed to the next step. It is actually completely independent of the file upload process.

It can go in two ways:
1 - ) User can choose to upload a data (browse with 'MyFiles' object - fileInput in UI) and then press Action Button to proceed forward.
2 - ) User can choose to directly press Action Button without data upload, then proceed forward (with limited app functionality; but not important here)

I tried the last piece of code you sent. I do not know why but when I try to upload a rather large data, ~80 MBs, disabling of the ActionButton does not occur immediately.

With -> observeEvent(input$MyFiles$datapath,, upload starts then a couple of seconds later ActionButton gets disabled and by that time Upload is completed already and there is no point in disabling the ActionButton anymore. Why would this occur I wonder. It looked so promising. Maybe it takes time to 'datapath' to get updated?

Hi @alptaciroglu. As you wanna disable the button during upload, first of all, I have to point out that the fileInput job is when you select the file in the client side, the file will upload to the the temp file of server side. And the input will provide the address of the uploaded temp file. That mean the upload file data still not in the R environment and you need to import the file data from the temp file. So, you can still do anything during uploading and will not affect or be affecting by the uploading process.

But never mind, if you want to disable the button during uploading data to the temp file, it is a little bit tricky and didn't know if any harm to the remaining script. You need to use javascript to make disableButton function. And add onchange attribute to trigger the disableButton function when the input file address is changed.

library(shiny)
library(shinyjs)

options(shiny.maxRequestSize = 1000*1024^2)

ui <- fluidPage(
    tags$script("function disableButton() {
  document.getElementById('ActionButton').disabled = true;
}"),
    titlePanel("Disable Action Button while File is uploading"),
    fileInput(
        inputId = "MyFiles",
        label = "Upload files"
    ) %>%
        {temp = .
        temp$children[[2]]$children[[1]]$children[[1]]$children[[2]]$attribs$onchange <- "disableButton()"
        temp},
    mainPanel(
        shinyjs::useShinyjs(),
        actionButton("ActionButton","Go")
    )
)

server <- function(input, output) {

    observeEvent(input$MyFiles$datapath,
                 {
                     enable("ActionButton")
                 })
}

shinyApp(ui = ui, server = server)
1 Like

Thank you @raytong Works brilliantly!

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