Search code examples
rshinyshinyjsrhandsontable

How to preserve manual edits to tables rendered with the rhandsontable package in R shiny?


The below code allows the user to manually edit values in the table rendered via rhandsontable, and furthermore, add columns to the table. However, when a column is added via the "Add" action button, all previous edits are erased. How can edits be preserved after adding a column?

I went through the solutions offered in How to save edits made using rhandsontable r package but they don't appear to work in my situation nor deal with columns adds. The below code uses the solution offered in the 2nd answer to that post, but it doesn't work in my case.

The idea is that "placeholder" assumptions are automatically presented in the table (mydata), and the user will always go through and edit those assumptions.

Code:

library(rhandsontable)
library(shiny)
library(shinyjs)

mydata <- data.frame('Col 1' = c(1,24,0,1), check.names = FALSE)
rownames(mydata) <- c('Term A','Term B','Term C','Term D') 

ui <- fluidPage(
  useShinyjs(), 
  br(),
  rHandsontableOutput("hottable"),br(),
  actionButton("addCol", "Add",width = '70px')
)

server <- function(input,output,session){
  
  observe({
    print(hot_to_r(input$hottable))
  })
  
  output$hottable = renderRHandsontable(dat())
  
  dat <- eventReactive(input$addCol, {
    if(input$addCol > 0){
      newcol <- data.frame(mydata[,1])
      names(newcol) <- paste("Col",ncol(mydata)+1)
      mydata <<- cbind(mydata, newcol)
    }
    rhandsontable(mydata,rowHeaderWidth = 100, useTypes = TRUE)
  }, ignoreNULL = FALSE)

}

shinyApp(ui,server)

Solution

  • A solution is presented below, using the reactiveVal() function described in https://shiny.rstudio.com/reference/shiny/1.3.0/reactiveVal.html, and the related posts How to add columns to a data frame rendered with rhandsontable in R Shiny with an action button? and Tonio Liebrand's solution in How to save edits made using rhandsontable r package:

    library(rhandsontable)
    library(shiny)
    
    mydata <- data.frame('Col 1' = c(1,24,0,1), check.names = FALSE)
    rownames(mydata) <- c('Term A','Term B','Term C','Term D') 
    
    ui <- fluidPage(
      rHandsontableOutput('hottable'),
      br(),actionButton('addCol', 'Add')
      )
    
    server <- function(input, output, session) {
      EmptyTbl <- reactiveVal(mydata)
      
      observeEvent(input$hottable, {
        EmptyTbl(hot_to_r(input$hottable))
      })
      
      output$hottable <- renderRHandsontable({
        rhandsontable(EmptyTbl())
      })
      
      observeEvent(input$addCol, {
        newCol <- data.frame(c(1,24,0,1))
        names(newCol) <- paste("Col", ncol(hot_to_r(input$hottable)) + 1)
        EmptyTbl(cbind(EmptyTbl(), newCol))
      })
      
    }
    
    shinyApp(ui, server)