L.Rop
L.Rop

Reputation: 55

Shiny r- How to disable checkboxgroup input after it is clicked?

Is there a way to disable a checkboxgroup element once it is clicked in shiny r?

I tried to figure out the problem, but without success. I add the checkboxgroup on which i am working. Thanks for your help!

library(shiny)

shinyUI(fluidPage(
  checkboxGroupInput("a","A",choices = 1:7),
  tags$head(HTML(
    '
    <script type="text/javascript">
    document.getElementById("a").onclick = function(){
        document.getElementById("a").disabled=true;
    }
    </script>
    '
  ))
  ))

shinyServer(function(input, output, session) {
  

  })

Upvotes: 3

Views: 4420

Answers (2)

Adam Spannbauer
Adam Spannbauer

Reputation: 2757

You can use the shinyjs package which conveniently comes with a disable function. You can trigger the disable with an observeEvent where the event is the checkbox value. The only caveat of using shinyjs is to incldue the function useShinyjs in your app's ui.

library(shiny)

ui <- shinyUI(fluidPage(
  shinyjs::useShinyjs(),
  checkboxGroupInput("a","A",choices = 1:7)
))

server <- shinyServer(function(input, output, session) {
  observeEvent(input$a, shinyjs::disable("a"))
})

shinyApp(ui,server)

The package has additional functions such as enable to enable a disabled element or toggleState to switch the element between the states of enabled/disabled.


Disabling Single Checkbox from a checkboxGroupInput

The disable function of shinyjs has a selector argument that can used to identify which elements to disable without using their shiny id. The way I identified what the correct query to pass to the selector was by using the SelectorGadget. The gadget gave a did not include the shinyid so I added a "B" checkbox group, and sure enough the id changed to include the shiny id "a" so I'm fairly confident this should work after adding more elements to the shiny App. Once the selector query was known the rest of the solution was identifying the label of which checkbox in the group was clicked, and building the string for the disable function to use. Hope this helps.

library(shiny)

ui <- shinyUI(fluidPage(
  shinyjs::useShinyjs(),
  #original checkbox group
  checkboxGroupInput("a","A",choices = 1:7),
  #additional checkbox group to identify how to work around multiple groups
  checkboxGroupInput("b","B",choices = 1:7)
))

server <- shinyServer(function(input, output, session) {

  #initialize reactive values (will use to store selected boxes to identify newest selection)
  rv <- reactiveValues()
  #initialize selected boxes to NULL
  rv$selectedBoxes <- NULL 
  
  observeEvent(input$a, {
    #extract newest selection by identifying which values are in a that have not been previously selected
    newSelection <- input$a[which(!(input$a %in% rv$selectedBoxes))]
    #create object that identifies newly selected checkbox (syntax found using selectorgadget)
    subElement <- paste0("#a .checkbox:nth-child(", newSelection,") label")
    #disable single checkbox of group
    shinyjs::disable(selector=subElement)
    #store all selected checkboxes
    rv$selectedBoxes <- input$a
  })
})

shinyApp(ui,server)

Upvotes: 10

Carl
Carl

Reputation: 5779

Two things:

tags$head(HTML(
    '
    <script type="text/javascript">
    document.getElementById("a").onclick = function(){
        document.getElementById("a").disabled=true;
    }
    </script>
    '
  ))

Should be:

tags$script(HTML(
    '
    document.getElementById("a").onclick = function(){
        document.getElementById("a").disabled=true;
    }
    '
  ))

This still doesn't work because checkboxGroupInput doesn't have an onclick event. If you use a different HTML element for "a" it works:

library(shiny)

shinyUI(fluidPage(
  actionButton("a","A"),
  tags$head(HTML(
    '
    document.getElementById("a").onclick = function(){
        document.getElementById("a").disabled=true;
    }
    '
  ))
  ))

shinyServer(function(input, output, session) {
  

  })

Upvotes: 0

Related Questions