Search code examples
rshinyreactable

Selecting multiple cells within the same group R reactable (and maybe actionButtons)


The code below produces the following table:

enter image description here

The Goal is to be able to select a category in the Manufacturer column (ex/ Buick) and have the 4 Models (2 from Midsize and 2 from Large) get selected. Right now the Select All feature only works by Models grouped by Type.

What I tried: ActionButton and observeEvent with updateReactable("table", selected = ...) The issue is that I want to give the users the ability to select all Models from multiple Manufacturer categories (ex/ The user selects all rows under Acura AND all rows under Buick). The action button I had tried only worked for one category and the table re-set if another button was clicked. Happy to include this failed code if it helps.

CODE:

library(shiny)
library(reactable)

data <- MASS::Cars93[, 1:7]

ui <- fluidPage(
  # actionButton("select_btn", "Select rows"),
  # actionButton("clear_btn", "Clear selection"),
  # actionButton("expand_btn", "Expand rows"),
  # actionButton("collapse_btn", "Collapse rows"),
  # actionButton("page_btn", "Change page"),
  # selectInput("filter_type", "Filter type", unique(data$Type), multiple = TRUE),
  reactableOutput("table")
)

server <- function(input, output) {
  output$table <- renderReactable({
    reactable(
      data,
      filterable = TRUE,
      searchable = TRUE,
      selection = "multiple",
      groupBy = c("Manufacturer",
                  "Type")

    )
  })
  
  # observeEvent(input$select_btn, {
  #   # Select rows
  #   updateReactable("table", selected = c(1, 3, 5))
  # })
  # 
  # observeEvent(input$clear_btn, {
  #   # Clear row selection
  #   updateReactable("table", selected = NA)
  # })
  # 
  # observeEvent(input$expand_btn, {
  #   # Expand all rows
  #   updateReactable("table", expanded = TRUE)
  # })
  # 
  # observeEvent(input$collapse_btn, {
  #   # Collapse all rows
  #   updateReactable("table", expanded = FALSE)
  # })
  # 
  # observeEvent(input$page_btn, {
  #   # Change current page
  #   updateReactable("table", page = 3)
  # })
  # 
  # observe({
  #   # Filter data
  #   filtered <- if (length(input$filter_type) > 0) {
  #     data[data$Type %in% input$filter_type, ]
  #   } else {
  #     data
  #   }
  #   updateReactable("table", data = filtered)
  # })
}

shinyApp(ui, server)

Solution

  • I found a solution that may work

    The Problem: I am trying to give the user the ability to select all Models within a given Type group and in addition the ability to select all Model within the larger Manufacturer group.

    My Solution: The user is able to select the different Manufacturers filter_man and this is stored in select_man.

    If the user started to select (via the checkbox) Models this is stored in selected. If this is omitted then if the user makes individual selections and afterwards decide the want to select Models from an entire Manufacturer group, the individual selections will be erased leaving only the selections from select_man. This is why the obsereEvent includes both selected() (individual cell selections) and select_man() (all models from a particular manufacturer)

    Code:

    library(shiny)
    library(reactable)
    
    data <- MASS::Cars93[, 1:7]
    
    ui <- fluidPage(
      selectInput("filter_man", "Manufacturer:", unique(data$Manufacturer), multiple = TRUE),
      actionButton("selections", "Select Manufacturer",class ="btn btn-primary btn-md"),
      reactableOutput("table")
    )
    
    server <- function(input, output) {
      
      
      output$table <- renderReactable({
        reactable(
          data,
          filterable = TRUE,
          searchable = TRUE,
          selection = "multiple",
          groupBy = c("Manufacturer",
                      "Type")
          
        )
      })
      
      selected <- reactive(getReactableState("table", "selected"))  
      
      select_man <- eventReactive(input$filter_man,{
        which(data$Manufacturer%in% input$filter_man )
      })
      
    
      
      observeEvent(input$selections, {
        # Select rows
        updateReactable("table", selected = c(selected(), select_man()))
      })
      
    }
    
    shinyApp(ui, server)