50

I am looking for a way to implement disabling/abling functionality over my shinyUI elements. Here xiaodaigh gives a hint how to disable/able an actionButton (see an image below) and this is my desired result, but the code does not do the trick with other gui elements I have tested (e.g. numericInput).

(I know a conditionalPanel feature, but this is not the effect I would like to have.)

I would strongly appreciate any suggestions, especially because I am not much familiar with JavaScript.

enter image description here

Marta Karas
  • 4,967
  • 10
  • 47
  • 77

3 Answers3

67

The reason the code you link to in your question doesn't work for other input widgets is because different input widgets need different JavaScript calls to get disabled. Another problems is that when shiny creates an input element, sometimes the id that you provide is the ID of the actual HTML input tag while sometimes that ID gets given to a container of the input tag.

The shinyjs package has a disable function that will work as-is with any shiny input. Disclaimer: I wrote that package.

Here is how you would achieve disabling a numericInput like you asked

library(shiny)
runApp(shinyApp(
  ui = fluidPage(
    shinyjs::useShinyjs(),
    numericInput("test", "Test", 5),
    actionButton("submit", "Choose")
  ),
  server = function(input, output, session) {
    observeEvent(input$submit, {
      shinyjs::disable("test")
    })
  }
))
DeanAttali
  • 25,268
  • 10
  • 92
  • 118
  • 2
    Is there a way to do this for a specific choice in a `selectInput()` widget? Following your instructions, it looks like it disables my `radioButtons()` widget no matter which option is selected in the `selectInput()` widget since the input to the server is not tied to the answer choices. – syntonicC Oct 20 '16 at 22:39
  • Unfortunately you cannot disable/enable specific options inside an input. That's true for checkboxes, radio, select, etc. It's simply because the entire input has an id, but the specific options do not – DeanAttali Oct 21 '16 at 04:46
  • `library(shinyjs)` is missing – Shahryar Mar 07 '17 at 23:17
  • 5
    @Shahryar the code given above will work, the `library()` call is not missing because I explicitly called the shinyjs functions by prepending `shinyjs::` to every function call – DeanAttali Mar 08 '17 at 04:57
  • Do you know if it's possible to disable an object before the server function? I have an UI that takes quite some time to load, and if I place the disabling functions into the server function, my objects will only fade once the rendering has been done. And I wouldn't want the user to see buttons first being active and suddenly, when the app is fully loaded, turning into inactivel – lazarea Sep 18 '19 at 16:41
  • In the app I am writing, if `x=0` then `y` is disabled and left to its default value, `NULL`. But one can set `x` to a positive number and this will enable `y`. With `y` enabled, we can set it to, say, an array of integers. We can then go back to `x` and set it to zero. This will disable `y`, but the values we entered previously will still be taken in by the app. Is there an easy way to fix this behaviour? – papgeo Apr 24 '23 at 14:32
10

The code suggested by Dean Attali can actually be slightly modified to achieve enabling and disabling as requested. See example below, which activates or deactivates the slider dependent on the value given (if value exceeds max of range slider is deactivated).

library(shiny)
runApp(shinyApp(
    ui = fluidPage(
        shinyjs::useShinyjs(),
        numericInput("val", "Choose value (max 10)", 5),
        sliderInput(inputId = "range",
                    label = "Range",
                    min = 0,
                    max = 10,
                    step = 0.1,
                    value = c(0,2))
    ),
    server = function(input, output, session) {
        observeEvent(input$val, {
            if(input$val <= 10){
                shinyjs::enable("range")
            }else{
                shinyjs::disable("range")
            }
        })
    }
))

tokami
  • 136
  • 1
  • 3
5

what about when your elements "vanish" when a certain condition is FALSE.

If this is your intention you can add this into your server.R

output$sliderInputUI <- renderUI({
    if (condition == TRUE) {
        sliderInput("id", "text", 
             min = 1, max = 8, 
             value = 1, step = 1
        )
    }
})

Add this to your ui.R htmlOutput("sliderInputUI")

sliderInput will then only appear in your ui when the condition is TRUE.

tnaake
  • 469
  • 5
  • 17