How to update rhandsontable output following manual row move?

127 Views Asked by At

I am trying to create an rhandsontable output that recalculates everytime a row is manually dragged and moved.

Through some searching on the internet, I have been able to produce a script where the output recalculates on the first manual row move, but cannot get it to update on subsequent row moves. I don't know how correct the existing method is, particularly the JS code section, but it seemed like a step in the right direction.

A simplified version of the current script is below. In this example, I would want the bottom row 'Value' to recalculate to 1 each time a row is dragged and moved. Currently, it only calculates the first time a row is dragged and moved.

    library(tidyverse)
    library(shiny)
    library(shinydashboard)
    library(rhandsontable)
    library(htmlwidgets)

underlying_table_data <- data.frame("Names" = c("A", "B", "C"), "Value" = c(0,0,0))

jsCode <- c(
    "function(el, x) {",
    "  Handsontable.hooks.add('afterRowMove', function(movedRows, finalIndex, dropIndex, movePossible, orderChanged){",
    "    Shiny.setInputValue('newRow', {movedRows: movedRows, finalIndex:finalIndex, dropIndex:dropIndex, movePossible: movePossible, orderChanged:orderChanged});",
    "  });",
    "}"
)

ui <- fluidPage(
               rHandsontableOutput("table"), 
)

server <- function(input, output) {

    values <- reactiveValues(data = underlying_table_data)

    output$table <- renderRHandsontable({
        rhandsontable(values$data, manualRowMove = T, readOnly = T) %>%
            onRender(jsCode)
    })

    observeEvent(
        input$newRow$movedRows,
           {if(!is.null(input$newRow$movedRows)){
                values$data[3, 'Value'] = 1
        }
        })
}

shinyApp(ui = ui, server = server)
1

There are 1 best solutions below

0
On BEST ANSWER

It's not the case that it only calculates the first time a row is dragged and moved - it calculates every time after a row is moved, but values$data[3, 'Value'] = 1 just says: Set the value of the Value column in the third row of the data to 1. What you need to do is to change the value in the rhandsontable object.

Therefore, you can change the JS to the following one and remove the observeEvent which is invoked after Shiny.setInputValue is called.

function(el, x) {
    Handsontable.hooks.add('afterRowMove', function() {
        this.setDataAtCell(this.countRows() - 1, 1, 1);
    });
}

enter image description here

library(shiny)
library(shinydashboard)
library(rhandsontable)
library(htmlwidgets)

underlying_table_data <- data.frame("Names" = c("A", "B", "C"), "Value" = c(0,0,0))

jsCode <- c(
    "function(el, x) {",
    "  Handsontable.hooks.add('afterRowMove', function(){",
    "    this.setDataAtCell(this.countRows() - 1, 1, 1);",
    "  });",
    "}"
)

ui <- fluidPage(
    rHandsontableOutput("table"), 
)

server <- function(input, output) {
    
    values <- reactiveValues(data = underlying_table_data)
    
    output$table <- renderRHandsontable({
        rhandsontable(values$data, manualRowMove = TRUE, readOnly = TRUE) |> 
            onRender(jsCode)
    })

}

shinyApp(ui = ui, server = server)