Reputation: 2400
I have implemented two columns with an all/none checkbox. Now I wish to be able to have some of the checkboxes pre-selected using, selected_states
, when the app starts.
The normal method of using selected =
fails because of how the all/none selector is implemented.
How can I keep the all/none functionality AND allow pre-selection of checkboxes?
library(shiny)
library(shinyWidgets)
library(tidyverse)
df <- tibble(
state = c("Alabama", "Alaska", "Arizona", "Arkansas",
"California", "Colorado", "Connecticut", "Delaware", "Florida",
"Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa",
"Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts",
"Michigan", "Minnesota", "Mississippi", "Missouri", "Montana",
"Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico",
"New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma",
"Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota",
"Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington",
"West Virginia", "Wisconsin", "Wyoming")
)
selected_states <- c("Alabama", "Alaska","Minnesota")
ui <- fluidPage(
wellPanel(
checkboxInput('all_none', 'All/None'),
tags$label("Choose :"),
fluidRow(
column(
width = 4,
checkboxGroupInput(
selected = selected_states,
inputId = "checka",
label = NULL,
choices = df$state[1:13]
)
),
column(
width = 4,
checkboxGroupInput(
selected = selected_states,
inputId = "checkb",
label = NULL,
choices = df$state[14:25]
)
)
)
),
textOutput("selected")
)
server <- function(input, output, session) {
observe({
updateCheckboxGroupInput(
session, 'checka', choices = df$state[1:13],
selected = if (input$all_none == TRUE) df$state
)
})
observe({
updateCheckboxGroupInput(
session, 'checkb', choices = df$state[14:25],
selected = if (input$all_none == TRUE) df$state
)
})
output$selected <- renderText({
all_selected <- paste(c(input$checka, input$checkb), collapse = ", ")
})
}
shinyApp(ui, server)
Upvotes: 1
Views: 578
Reputation: 9857
You should move the code that selects/deselects all the states so that it runs when the All/None checkbox is clicked.
To stop that code running at startup, you can use the ignoreInit argument.
library(shiny)
library(tidyverse)
df <- tibble(
state = c("Alabama", "Alaska", "Arizona", "Arkansas",
"California", "Colorado", "Connecticut", "Delaware", "Florida",
"Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa",
"Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts",
"Michigan", "Minnesota", "Mississippi", "Missouri", "Montana",
"Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico",
"New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma",
"Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota",
"Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington",
"West Virginia", "Wisconsin", "Wyoming")
)
selected_states <- c("Alabama", "Alaska","Minnesota")
ui <- fluidPage(
wellPanel(
checkboxInput('all_none', 'All/None'),
tags$label("Choose :"),
fluidRow(
column(
width = 4,
checkboxGroupInput(
selected = selected_states,
inputId = "checka",
label = NULL,
choices = df$state[1:13]
)
),
column(
width = 4,
checkboxGroupInput(
selected = selected_states,
inputId = "checkb",
label = NULL,
choices = df$state[14:25]
)
)
)
),
textOutput("selected")
)
server <- function(input, output, session) {
observeEvent(input$all_none,{
updateCheckboxGroupInput(
session, 'checka', choices = df$state[1:13],
selected = if (input$all_none == TRUE) df$state
)
updateCheckboxGroupInput(
session, 'checkb', choices = df$state[14:25],
selected = if (input$all_none == TRUE) df$state
)
}, ignoreInit = 1)
output$selected <- renderText({
all_selected <- paste(c(input$checka, input$checkb), collapse = ", ")
})
}
shinyApp(ui, server)
Upvotes: 1
Reputation: 84
I would probably replace the single All/None button with separate actionButtons for "Select All" and "Select None". The code could then look like this:
library(shiny)
library(shinyWidgets)
library(tidyverse)
df <- tibble(
state = c("Alabama", "Alaska", "Arizona", "Arkansas",
"California", "Colorado", "Connecticut", "Delaware", "Florida",
"Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa",
"Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts",
"Michigan", "Minnesota", "Mississippi", "Missouri", "Montana",
"Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico",
"New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma",
"Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota",
"Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington",
"West Virginia", "Wisconsin", "Wyoming")
)
selected_states <- c("Alabama", "Alaska","Minnesota")
ui <- fluidPage(
wellPanel(
actionButton('selectall','Select All'),
actionButton('selectnone','Select None'),
br(),
br(),
tags$label("Choose :"),
fluidRow(
column(
width = 4,
checkboxGroupInput(
selected = selected_states,
inputId = "checka",
label = NULL,
choices = df$state[1:13]
)
),
column(
width = 4,
checkboxGroupInput(
selected = selected_states,
inputId = "checkb",
label = NULL,
choices = df$state[14:25]
)
)
)
),
textOutput("selected")
)
library(shiny)
?updateCheckboxGroupInput
server <- function(input, output, session) {
observeEvent(
input$selectall, {
updateCheckboxGroupInput(
session, 'checka',
choices = df$state[1:13],
selected = df$state)
}
)
observeEvent(
input$selectall, {
updateCheckboxGroupInput(
session, 'checkb',
choices = df$state[14:25],
selected = df$state)
}
)
observeEvent(
input$selectnone, {
updateCheckboxGroupInput(
session, 'checka',
choices = df$state[1:13],
selected = character(0))
}
)
observeEvent(
input$selectnone, {
updateCheckboxGroupInput(
session, 'checkb',
choices = df$state[14:25],
selected = character(0))
}
)
output$selected <- renderText({
all_selected <- paste(c(input$checka, input$checkb), collapse = ", ")
})
}
shinyApp(ui, server)
Incidentally, if you'd like all 25 states to appear in a single selector, but formatted as two columns, you could use the CSS property column-count
applied to the checkboxGroupInput
- this would allow you to use a single selector, thereby simplifying the code but resulting in the same appearance:
library(shiny)
library(shinyWidgets)
library(tidyverse)
df <- tibble(
state = c("Alabama", "Alaska", "Arizona", "Arkansas",
"California", "Colorado", "Connecticut", "Delaware", "Florida",
"Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa",
"Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts",
"Michigan", "Minnesota", "Mississippi", "Missouri", "Montana",
"Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico",
"New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma",
"Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota",
"Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington",
"West Virginia", "Wisconsin", "Wyoming")
)
selected_states <- c("Alabama", "Alaska","Minnesota")
ui <- fluidPage(
tags$head(
tags$style(HTML("
div .shiny-options-group {
column-count: 2;
}
"))
),
wellPanel(
actionButton('selectall','Select All'),
actionButton('selectnone','Select None'),
br(),
br(),
tags$label("Choose :"),
fluidRow(
column(
width = 8,
checkboxGroupInput(
selected = selected_states,
inputId = "checka",
label = NULL,
choices = df$state[1:25]
)
)
)
),
textOutput("selected")
)
library(shiny)
?updateCheckboxGroupInput
server <- function(input, output, session) {
observeEvent(
input$selectall, {
updateCheckboxGroupInput(
session, 'checka',
choices = df$state[1:25],
selected = df$state)
}
)
observeEvent(
input$selectnone, {
updateCheckboxGroupInput(
session, 'checka',
choices = df$state[1:25],
selected = character(0))
}
)
output$selected <- renderText({
all_selected <- paste(c(input$checka, input$checkb), collapse = ", ")
})
}
shinyApp(ui, server)
Upvotes: 1