Pabort
Pabort

Reputation: 348

Enable/disable a button using a reactive expression

I'm developing a shiny app. I require the user to choose first how does he/she want to upload data, by file or choosing an environment variable, using a radio button.
Once this is selected, depending on this choice, user can upload a file or select a variable.
I have a button to make the app compute a plot based on the data provided by the user. I want the button to be disabled until I have the data provided, but I'm unable to make shinyjs to enable the button based on the existence of the reactive expression where I store the user's data.

Here is an example:

library(shiny)

shinyApp(
    ui = fluidPage(
        useShinyjs(),
        radioButtons("dataSourceType", "Select data source:",
                     c("From file" = "file",
                       "From workspace" = "var")),
        conditionalPanel(
            condition = "input.dataSourceType == 'file'",
            fileInput("dataFile", "Choose data file:")
        ),
        conditionalPanel(
            condition = "input.dataSourceType == 'var'", 
            selectInput("dataVar", "Choose data var:",
                        ls(envir=.GlobalEnv))
        ),
        disable(actionButton("btn", "Click me")),
        textOutput("text")
        
    ),
    server = function(input, output) {
        data <- reactive({
            if(input$dataSourceType=="file"){
                req(input$dataSourceType)
                return(read.csv(file=input$dataFile$datapath))
            } else {
                req(input$dataVar)
                get(input$dataVar)
            }
        })
        
        observe({
            if(isTruthy(data())){
                enable("btn")
            } else {
                disable("btn")
            }
        })
        
        observeEvent(input$btn, {
            output$text <- renderText({
                head(as.character(data()))
            })
        })
    }
)

Upvotes: 0

Views: 623

Answers (1)

YBS
YBS

Reputation: 21297

To disable the button, you need to ensure that you return a NULL value for data() when user file is not provided in input$dataFile. Try this

library(shiny)
library(shinyjs)
library(DT)

shinyApp(
  ui = fluidPage(
    useShinyjs(),
    sidebarLayout(
      sidebarPanel(
        radioButtons("dataSourceType", "Select data source:",
                     c("From file" = "file",
                       "From workspace" = "var")),
        conditionalPanel(
          condition = "input.dataSourceType = 'file'",
          fileInput("dataFile", "Choose data file:")
        ),
        conditionalPanel(
          condition = "input.dataSourceType = 'var'", 
          selectInput("dataVar", "Choose data var:",
                      ls(envir=.GlobalEnv))
        ),
        actionButton("btn", "Click me")
      ),
      mainPanel(
        DTOutput("t1")
        #, textOutput("text")
      )
    )
  ),
  server = function(input, output,session) {
    data <- reactive({
      req(input$dataSourceType)
      if(input$dataSourceType=="file"){
        if (is.null(input$dataFile)) {return(NULL)
        }else return(read.csv(file=input$dataFile$datapath, header=TRUE, sep=","))
      } else {
        req(input$dataVar)
        get(input$dataVar)
      }
    })

    observe({
      if(!is.null(data())){
        shinyjs::enable("btn")
      }else {
        shinyjs::disable("btn")
      }
    })
    
    observeEvent(input$btn, {
      req(data())
      output$text <- renderText({
        head(as.character(data()))
      })
      output$t1 <- renderDT(data())
    })
  }
)

Upvotes: 1

Related Questions