Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to have different dropdown options for different rows in an rhandsontable?

I am making a shiny app where the user needs to select dropdown options in a table. I am using rhandsontable, however it seems like I am only able to have one set of dropdown options for a single column. So row 1 has the same options as row 800. I want row 1 to have a different set of dropdown option than row 800.

Is there a way to do this?

I've thought about creating separate tables and pushing them together to look like one table. Only the first table would have column headers, and all other tables below it would not have column headers. I am trying to avoid this because rhandsontables have horizontal and vertical scroll bars, and there wouldn't be a way to sync the scroll bars between multiple tables. That would make the "one table" look a bit off. Actually having all the data in a single table would look and function much better.

I have a super simple example below:

  require(shiny)
  require(rhandsontable)

  ui <- fluidPage(
    hr(""),

    # Display table
    mainPanel(rHandsontableOutput("ExampleTable"))
  )

  server <- function(input, output) {

    output$ExampleTable <- renderRHandsontable({

      # creating table that will be displayed 
      df <- data.frame(Object = c("car", "car", "car", "house", "house", "house"), Needs = NA, stringsAsFactors = FALSE)

      # defining dropdown options
      dropdownOptions <- c("tires", "wipers", "headlights", "gutters", "carpet")

      rhandsontable(df, rowHeaders = NULL, stretchH = "all") %>%
        hot_col("Object", readOnly = TRUE) %>%
        hot_col("Needs", type = "dropdown", source = dropdownOptions)

    })
  }

  # Run the application 
  shinyApp(ui = ui, server = server)

I would like the dropdown options to only include "tires", "wipers", and "headlights" for all rows where the Object column has a value of "car". Because cars can never need gutters or carpet, I don't want the user to have the ability to select either of those options.

For each row where "house" is the value in the Object column, the user should only have two options displayed in the dropdown..."gutters" and "carpet". This will help avoid user error.

like image 494
Joe Z Avatar asked Aug 23 '19 23:08

Joe Z


1 Answers

Here is a working solution based on my example I shared here (and @Ben mentioned above):

library(shiny)
library(rhandsontable)

ui <- fluidPage(
  hr(),
  # Display table
  mainPanel(rHandsontableOutput("ExampleTable"))
)

server <- function(input, output) {
  
  # creating table that will be displayed 
  DF <- reactiveVal(data.frame(Object = c("car", "car", "car", "house", "house", "house"), Needs = NA_character_, stringsAsFactors = FALSE))
  
  # update df() on user changes
  observeEvent(input$ExampleTable, {
    DF(hot_to_r(input$ExampleTable))
  })
  
  output$ExampleTable <- renderRHandsontable({

    # defining dropdown options
    carOptions <- c(NA_character_, "tires", "wipers", "headlights")
    houseOptions <- c(NA_character_, "gutters", "carpet")
    
    tmpExampleTable <- rhandsontable(DF(), rowHeaders = NULL, stretchH = "all", selectCallback = TRUE, width = 300, height = 300) %>%
      hot_col("Object", readOnly = TRUE) %>%
      hot_col("Needs", allowInvalid = FALSE, type = "dropdown", source = NA_character_, readOnly = TRUE)
    
    if(!is.null(input$ExampleTable_select$select$r)){
      
      selectedObject <- DF()[input$ExampleTable_select$select$r, "Object"]
      
      if(selectedObject == "car"){
        tmpExampleTable <- hot_col(tmpExampleTable, col = "Needs", allowInvalid = FALSE, type = "dropdown", source = carOptions) %>% hot_cell(row = input$ExampleTable_select$select$r, col = "Needs", readOnly = FALSE)
      }
      
      if(selectedObject == "house"){
        tmpExampleTable <- hot_col(tmpExampleTable, col = "Needs", allowInvalid = FALSE, type = "dropdown", source = houseOptions) %>% hot_cell(row = input$ExampleTable_select$select$r, col = "Needs", readOnly = FALSE)
      }
    }
    
    tmpExampleTable
    
  })
}

# Run the application 
shinyApp(ui = ui, server = server)

Edit: Here you can find a generalized approach for dependent rhandsontable dropdowns.

like image 103
ismirsehregal Avatar answered Oct 25 '22 10:10

ismirsehregal