I am trying to use Shiny's checkboxGroupInput()
so it offers the user a binary choice, where selecting one option automatically deselects the other. I try this in the below MWE code. It works fine when Option 1 is currently selected and the user clicks on Option 2. But it doesn't work when going the other direction: if Option 2 is currently selected and user clicks Option 1, nothing happens: the user has to first click on Option 2 to deselect it and then can click on Option 1 to select it. I would like clicking one to autmotically deselect the other. There should be no scenario where input$choice
= none; has to be either "Option 1" or "Option 2", full stop.
I could use radioButton()
. I've also tried a custom button that works but is very cumbersome. The reason I'm trying to use checkboxGroupInput()
is for formatting ease and consistency, because I have a large table of checkboxes where I use checkboxGroupInput()
as intended for multiple choices but I also have some binary "either/or" selections thrown in; being able to use checkboxGroupInput()
for all will be far simpler.
library(shiny)
ui <- fluidPage(
checkboxGroupInput(
"choice",
"Select one option:",
choices = c("Option 1", "Option 2"),
selected = "Option 1"
),
textOutput("selected_choice")
)
server <- function(input, output, session) {
observe({
if (length(input$choice) > 1) {
last_choice <- tail(input$choice, 1)
updateCheckboxGroupInput(session, "choice", selected = last_choice)
}
})
output$selected_choice <- renderText({
if (is.null(input$choice)) {
"Selected: none"
} else {
paste("Selected:", input$choice)
}
})
}
shinyApp(ui, server)
Edit OP: I am trying to mimic a radio button but using the Shiny checkboxGroupInput() function, for aesthetic reasons only. I added a javascript solution as an Answer.
Try to save the previous choice and setdifferent
to the newly selected choice to set the new value correctly. The problem is, that checkboxGroupInput
allows multiple selections by design. So if you select the 2nd box, the selection is: [option 1, option2 ] where you use tail to get the later.
If we go the other way around (selecting the first box from the second), the selection still is [option 1, option2 ] which tail still gives option2. So we have to somehow track the previous selection.
library(shiny)
ui <- fluidPage(
checkboxGroupInput(
"choice",
"Select one option:",
choices = c("Option 1", "Option 2"),
selected = "Option 1"
),
textOutput("selected_choice")
)
server <- function(input, output, session) {
prev_choice <- reactiveVal("Option 1") # track it
observeEvent(input$choice, {
if (length(input$choice) > 1) {
new_choice <- setdiff(input$choice, prev_choice())
prev_choice(new_choice)
updateCheckboxGroupInput(session, "choice", selected = new_choice) # Keep new choice
}
})
output$selected_choice <- renderText({
if (is.null(input$choice)) {
"Selected: none"
} else {
paste("Selected:", input$choice)
}
})
}
shinyApp(ui, server)