What I am trying to do: If I paste multiple values at once into a row into the shiny app with an integrated rhandsontable, that all the new values get a color change of the background at the same time.
with the answer from here the background color change works, but only if I paste the new values in the cells one by one and not row-wise: Change cell background of rHandsontable with afterChange event on client side
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 = "reset_button",label = "Reset")
,rHandsontableOutput(outputId="mtcars"))
server <- function(input, output, session) {
reset <- reactiveVal(0)
output$mtcars <- renderRHandsontable({
r = reset()
rht = rhandsontable(mtcars,reset=r,stretchH="all",height=300)
reset(0)
htmlwidgets::onRender(rht,change_hook)
})
observeEvent(input$reset_button,
{
reset(1)
})
}
shinyApp(ui, server)
code modified from the answer of here
I tried to implement a for-loop in the changefn function, however unfortunately that did not work
Things change all the time, but this seems like it's overly complex for something that doesn't have to be. You only need a change event if all you want to do is color changed cells.
You won't need to specify whether it was pasted, filled, etc. If there is a change for any reason, this function looks at it.
I used a bit of JQuery here instead of for loops. I also didn't make as many variables. For example, change
is used in for each changes
(change is each index of changes). cellchng
is used in for each cellchngs
.
change_hook <- "function(el,x) {
hot = this.hot;
cellchngs = [];
afterChange = function(changes, source) {
$.each(changes, function (index, elem) {
change = elem; /* gather the row, col, old, new values */
if(change[2] !== change[3]) { /* if old isn't the same as new */
cellchg = ({rowind: change[0], colind: change[1]});
cellchngs.push(cellchg); /* add row and column indicies to array */
}
});
$.each(cellchngs, function(ind, elem) {
td = hot.getCell(elem['rowind'], elem['colind']); /* get the html element */
td.style.background = 'cyan'; /* set background color */
});
}
hot.addHook('afterChange', afterChange); /* add event to table */
}"
Nothing in your Shiny code needs to change.