rshinyrhandsontable

How to repeat hot_cell for rhandsontable? hot_cells?


I intended to use hot_cell from rhandsontable in a shiny app to disable a cell when a checkbox is TRUE.

For my example, I'm using mtcars, and any row with a TRUE in the last column should disable the cyl column for that row. Using hot_cell, I can make individual rows as readOnly. However, it applies only to a single cell.

Is there a function I'm not seeing like hot_cells? Alternatively, I thought of using renderer to accomplish this, but I'm not sure how to do that. I know there should be a way, but I'm not sure how to translate this JavaScript to match, here's a JavaScript example: https://jsfiddle.net/ddan/1rhrco48/ My code will note some of my failed attempts with JavaScript.

Example code:

library(shiny)
library(rhandsontable)

ui <- fluidPage(
  rHandsontableOutput("Test")
)

server <- function(input, output, session) {
  
  #reactiveValues - Will store the table after editings
  temp_RV <- reactiveValues("DF" = cbind(mtcars, data.frame("Check" = FALSE)))
  
  #When the table is edited, update the reactiveValue
  observeEvent(input$Test, {
    
    temp_RV$DF <- hot_to_r(input$Test)
    
  })
  
  
  output$Test <- renderRHandsontable({
    
    #Only render if reactiveValue exists
    if(!is.null(temp_RV$DF)) {
      
      rhandsontable(temp_RV$DF) %>%
        #This works
        hot_cell(row = 1, col = "cyl", readOnly = TRUE) %>%
        #Below only works for a single cell, but if there are multiple it won't work. I need a "hot_cells?"
        # hot_cell(which(temp_RV$DF$Check), "cyl", readOnly = TRUE)  %>%
        #I thought maybe it needed "cyl" multiple times, so I tried below. Did not work. 
        # Makes sense, help specifies this configures a "single cell".
        # hot_cell(which(temp_RV$DF$Check), rep("cyl", sum(temp_RV$DF$Check)), readOnly = TRUE)
        #Below is using a renderer. I've tried things like td.disabled = 'true'; td.style = 'disabled'; td.editable = 'false';
        #These don't work when tried, and I'm not seeing a td.style that works for this.
        #td = disabled; will disable essentially the whole table, so this doesn't quite work. 
        hot_col(col = "cyl", renderer = paste0("
         function (instance, td, row, col, prop, value, cellProperties) {
         Handsontable.renderers.NumericRenderer.apply(this, arguments);
         var col_value11 = instance.getData()[row][11]
         
         if (col_value11) {
            td.style.background = '#4c433c';
         }  else {
            td.style.background = '#93d7ff';
          }
         
         }
         "))
      
    }
    
  })
}

shinyApp(ui, server)

Solution

  • Inside the renderer, set cellProperties.readOnly to true or false:

    library(shiny)
    library(rhandsontable)
    
    ui <- fluidPage(
      rHandsontableOutput("Test")
    )
    
    server <- function(input, output, session) {
      
      #reactiveValues - Will store the table after editings
      temp_RV <- reactiveValues("DF" = cbind(mtcars, data.frame("Check" = FALSE)))
      
      #When the table is edited, update the reactiveValue
      observeEvent(input$Test, {
        temp_RV$DF <- hot_to_r(input$Test)
      })
      
      output$Test <- renderRHandsontable({
        
        #Only render if reactiveValue exists
        if(!is.null(temp_RV$DF)) {
          
          rhandsontable(temp_RV$DF) %>%
            hot_col(col = "cyl", renderer = paste0("
             function (instance, td, row, col, prop, value, cellProperties) {
               Handsontable.renderers.NumericRenderer.apply(this, arguments);
               var col_value11 = instance.getData()[row][11]
             
               if (col_value11) {
                 td.style.background = '#4c433c';
                 cellProperties.readOnly = true;
               } else {
                 td.style.background = '#93d7ff';
                 cellProperties.readOnly = false;
               }
             
             }
             "))
        }
      })
    }
    
    shinyApp(ui, server)