rshinyshinyjs

shinyjs::enable not working for fileInput in shiny (R)


In my shiny app, I have the fileInput disabled after the data was loaded. I also have a conditional reset button, that lets the user start over from scratch. However, while shinyjs::disable() is working great for my fileInput, shinyjs::enable() is being ignored and the input is not reactivated after being reset. Am I missing something? Is there a different way to re-enable the input? It's also not resetting the look from 'disabled' to 'enabled' despite removing the class.

Is it because I'm running multiple consecutive js on the same input? Can I combine them into one runjs()? I'm not very familiar with JS.

library(shiny)
library(shinyjs)

ui <- fluidPage(
  shinyjs::useShinyjs(),
  tags$head(tags$style(".shiny-file-input-progress {display: none}")),
  fileInput("file", label=NULL, buttonLabel="Get File", placeholder=NULL),
  uiOutput('reset')
)

server <- function(input, output, session) {
  
  dataloaded<-reactiveVal()
  
  observeEvent(input$file,{
    
    #...loading the data and doing something with it...
    
    shinyjs::disable("file") #disable the button
    runjs('$("#file").parents("span").addClass("disabled")') #make it look disabled
    runjs("var button = document.querySelector('.btn-file');button.textContent = 'Done';")  #change the label
    dataloaded(T)
  })
  
  output$reset <- renderUI({
    req(dataloaded())
    actionButton("reset", "Reset")
  })
  
  observeEvent(input$reset,{
    dataloaded(NULL)
    shinyjs::enable("file") 
    runjs("var button = document.querySelector('.btn-file');button.textContent = 'Get File';")
    runjs('$("#file").parents("span").removeClass("disabled")')
  })

}

shinyApp(ui,server)

Solution

  • The problem is that inside the observeEvent for input$file you are doing this:

    var button = document.querySelector('.btn-file');
    
    button.textContent = 'Done'; #change the label
    

    However, notice what is written at MDN:

    Warning: Setting textContent on a node removes all of the node's children and replaces them with a single text node with the given string value.

    So you are in particular removing file and later shinyjs::enable("file") can't find it.

    Instead as above, do it like this:

    var button = document.querySelector('.btn-file');
    
    button.childNodes[0].nodeValue = 'Done';