Sunday, 18 June 2023

Rhandsontable/shiny/ undo

I have a shiny app with an integrated rhandsontable, I have a "undo" button which undoes all changes at once (so for example if I changed 5 values, then click "undo" all 5 values are reverted simultaneously)

Is there any possibility to implement a second version of the undo button so that the changes are reverted one by one, so undo would only revert the single most recent change, i.e. after changing 3 values, I would have to click the undo button 3 times to revert all changes?

library(shiny)
library(rhandsontable)

change_hook <- "function(el,x) {
var hot = this.hot;  
var cellChanges = [];

var changefn = function(changes,source) { 
if (source === 'edit' || source === 'undo' || source === 'autofill' || source === 'paste') {
row = changes[0][0];
col = changes[0][1];
oldval = changes[0][2];
newval = changes[0][3];

if (oldval !== newval) {
  var cell = hot.getCell(row, col);
  cell.style.background = 'cyan';
  cellChanges.push({'rowid':row, 'colid':col});
}
}
}

var renderfn = function(isForced) {

for(i = 0; i < cellChanges.length; i++)
{

var rowIndex = cellChanges[i]['rowid'];
var columnIndex = cellChanges[i]['colid'];

var cell = hot.getCell(rowIndex, columnIndex);
cell.style.background = 'cyan';

}


}

var loadfn = function(initialLoad) {

for(i = 0; i < cellChanges.length; i++)
    {
      var rowIndex = cellChanges[i]['rowid'];
      var columnIndex = cellChanges[i]['colid'];

      var cell = hot.getCell(rowIndex, columnIndex);

      cell.style.background = 'white';

    }
cellChanges = []

}


hot.addHook('afterChange', changefn);
hot.addHook('afterRender', renderfn);
hot.addHook('afterLoadData', loadfn);


}  "


ui <- div(actionButton(inputId = "undo_button",label = "undo")
          ,rHandsontableOutput(outputId="mtcars"))


server <- function(input, output, session) {
  
  
  undo <- reactiveVal(0)
  output$mtcars <- renderRHandsontable({
    r = undo()
    rht = rhandsontable(mtcars,reset=r,stretchH="all",height=300)
    undo(0)
    htmlwidgets::onRender(rht,change_hook)
  })
  
  observeEvent(input$undo_button,
               {
                 undo(1)
               })
}

 shinyApp(ui, server)


from Rhandsontable/shiny/ undo

No comments:

Post a Comment